Data Exploration and Wrangling
The first step in performing any data analysis is to explore the data.
For example, we might want to better understand the variables included in the data, as we may learn about important details about the data that we should keep in mind as we try to predict our outcome variable.
First, let’s just get a general sense of our data. We can do that using the glimpse() function of the dplyr package (it is also in the tibble package).
We will also use the %>% pipe, which can be used to define the input for later sequential steps.
This will make more sense when we have multiple sequential steps using the same data object.
To use the pipe notation we need to install and load dplyr as well.
For example, here we start with pm data object and “pipe” the object into as input into the glimpse() function. The output is an overview of what is in the pm object such as the number of rows and columns, all the column names, the data types for each column and the first view values in each column. The output below is scrollable so you can see everything from the glimpse() function.
# Scroll through the output!
pm %>%
dplyr::glimpse()
Rows: 876
Columns: 50
$ id <dbl> 1003.001, 1027.000, 1033.100, 1049.100,...
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.6590...
$ fips <dbl> 1003, 1027, 1033, 1049, 1055, 1069, 107...
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.28763,...
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85.96...
$ state <chr> "Alabama", "Alabama", "Alabama", "Alaba...
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKalb",...
$ city <chr> "Fairhope", "Ashland", "Muscle Shoals",...
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.534772,...
$ zcta <dbl> 36532, 36251, 35660, 35962, 35901, 3630...
$ zcta_area <dbl> 190980522, 374132430, 16716984, 2038362...
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 30217, ...
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038, 5....
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.867...
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.231...
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.0316...
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.9730...
$ county_area <dbl> 4117521611, 1564252280, 1534877333, 201...
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430, 10...
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.721489,...
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.517193,...
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409411...
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173626...
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.90959,...
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.310155,...
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.585843,...
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.214...
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.50894,...
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.353...
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.55979,...
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, ...
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, ...
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665,...
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.0...
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.3...
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920,...
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.3308...
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 40.7...
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2....
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1...
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37....
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23....
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0...
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, ...
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7...
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5,...
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61....
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, ...
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, ...
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.08333,...
We can see that there are 876 monitors (rows) and that we have 50 total variables (columns) - one of which is the outcome variable. In this case, the outcome variable is called value.
Notice that some of the variables that we would think of as factors (or categorical data) are currently of class character as indicated by the <chr> just to the right of the column names/variable names in the glimpse() output. This means that the variable values are character strings, such as words or phrases.
The other variables are of class <dbl>, which stands for double precision which indicates that they are numeric and that they have decimal values. In contrast, one could have integer values which would not allow for decimal numbers. Here is a link for more information on double precision numeric values.
Another common data class is factor which is abbreviated like this: <fct>. A factor is something that has unique levels but there is no appreciable order to the levels. For example we can have a numeric value that is just an id that we want to be interpreted as just a unique level and not as the number that it would typically indicate. This would be useful for several of our variables:
- the monitor ID (
id)
- the Federal Information Processing Standard number for the county where the monitor was located (
fips)
- the zip code tabulation area (
zcta)
None of the values actually have any real numeric meaning, so we want to make sure that R does not interpret them as if they do.
So let’s convert these variables into factors. We can do this using the across() function of the dplyr package and the as.factor() base function. The across() function has two main arguments: (i) the columns you want to operate on and (ii) the function or list of functions to apply to each column.
In this case, we are also using the magrittr assignment pipe or double pipe that looks like this %<>% of the magrittr package. This allows us use the pm data as input, but also reassigns the output to the same data object name.
# Scroll through the output!
pm %<>%
mutate(across(c(id, fips, zcta), as.factor))
glimpse(pm)
Rows: 876
Columns: 50
$ id <fct> 1003.001, 1027.0001, 1033.1002, 1049.10...
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.6590...
$ fips <fct> 1003, 1027, 1033, 1049, 1055, 1069, 107...
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.28763,...
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85.96...
$ state <chr> "Alabama", "Alabama", "Alabama", "Alaba...
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKalb",...
$ city <chr> "Fairhope", "Ashland", "Muscle Shoals",...
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.534772,...
$ zcta <fct> 36532, 36251, 35660, 35962, 35901, 3630...
$ zcta_area <dbl> 190980522, 374132430, 16716984, 2038362...
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 30217, ...
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038, 5....
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.867...
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.231...
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.0316...
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.9730...
$ county_area <dbl> 4117521611, 1564252280, 1534877333, 201...
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430, 10...
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.721489,...
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.517193,...
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409411...
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173626...
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.90959,...
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.310155,...
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.585843,...
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.214...
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.50894,...
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.353...
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.55979,...
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, ...
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, ...
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665,...
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.0...
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.3...
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920,...
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.3308...
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 40.7...
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2....
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1...
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37....
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23....
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0...
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, ...
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7...
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5,...
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61....
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, ...
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, ...
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.08333,...
Great! Now we can see that these variables are now factors as indicated by <fct> after the variable name.
skim package
The skim() function of the skimr package is also really helpful for getting a general sense of your data. By design, it provides summary statistics about variables in the data set.
Notice how there is a column called n_missing about the number of values that are missing.
This is also indicated by the complete_rate variable (or missing/number of observations).
In our data set, it looks like our data do not contain any missing data.
Also notice how the function provides separate tables of summary statistics for each data type: character, factor and numeric.
Next, the n_unique column shows us the number of unique values for each of our columns. We can see that there are 49 states represented in the data.
We can see that for many variables there are many low values as the distribution shows two peaks, one near zero and another with a higher value.
This is true for the imp variables (measures of development), the nei variables (measures of emission sources) and the road density variables.
We can also see that the range of some of the variables is very large, in particular the area and population related variables.
Let’s take a look to see which states are included using the distinct() function of the dplyr package:
pm %>%
dplyr::distinct(state)
Scroll through the output:
It looks like “District of Columbia” is being included as a state. We can see that Alaska and Hawaii are not included in the data.
Let’s also take a look to see how many monitors there are in a few cities. We can use the filter() function of the dplyr package to do so. For example, let’s look at Albuquerque, New Mexico.
pm %>% dplyr::filter(city == "Albuquerque")
# A tibble: 2 x 50
id value fips lat lon state county city CMAQ zcta zcta_area
<fct> <dbl> <fct> <dbl> <dbl> <chr> <chr> <chr> <dbl> <fct> <dbl>
1 3500~ 5.98 35001 35.1 -107. New ~ Berna~ Albu~ 10.1 87109 26199125
2 3500~ 5.91 35001 35.1 -107. New ~ Berna~ Albu~ 10.1 87108 15224438
# ... with 39 more variables: zcta_pop <dbl>, imp_a500 <dbl>, imp_a1000 <dbl>,
# imp_a5000 <dbl>, imp_a10000 <dbl>, imp_a15000 <dbl>, county_area <dbl>,
# county_pop <dbl>, log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
# log_pri_length_10000 <dbl>, log_pri_length_15000 <dbl>,
# log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
# log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
# log_prisec_length_10000 <dbl>, log_prisec_length_15000 <dbl>,
# log_prisec_length_25000 <dbl>, log_nei_2008_pm25_sum_10000 <dbl>,
# log_nei_2008_pm25_sum_15000 <dbl>, log_nei_2008_pm25_sum_25000 <dbl>,
# log_nei_2008_pm10_sum_10000 <dbl>, log_nei_2008_pm10_sum_15000 <dbl>,
# log_nei_2008_pm10_sum_25000 <dbl>, popdens_county <dbl>,
# popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>, hs <dbl>, somecollege <dbl>,
# associate <dbl>, bachelor <dbl>, grad <dbl>, pov <dbl>, hs_orless <dbl>,
# urc2013 <dbl>, urc2006 <dbl>, aod <dbl>
We can see that there were only two monitors in the city of Albuquerque in 2006. Let’s compare this with Baltimore.
pm %>% dplyr::filter(city == "Baltimore")
# A tibble: 5 x 50
id value fips lat lon state county city CMAQ zcta zcta_area
<fct> <dbl> <fct> <dbl> <dbl> <chr> <chr> <chr> <dbl> <fct> <dbl>
1 2451~ 12.2 24510 39.3 -76.6 Mary~ Balti~ Balt~ 10.9 21251 461424
2 2451~ 12.5 24510 39.3 -76.7 Mary~ Balti~ Balt~ 10.9 21215 17645223
3 2451~ 12.8 24510 39.3 -76.5 Mary~ Balti~ Balt~ 10.9 21224 24539976
4 2451~ 14.3 24510 39.2 -76.6 Mary~ Balti~ Balt~ 10.9 21226 25718732
5 2451~ 13.3 24510 39.3 -76.6 Mary~ Balti~ Balt~ 10.9 21202 4111039
# ... with 39 more variables: zcta_pop <dbl>, imp_a500 <dbl>, imp_a1000 <dbl>,
# imp_a5000 <dbl>, imp_a10000 <dbl>, imp_a15000 <dbl>, county_area <dbl>,
# county_pop <dbl>, log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
# log_pri_length_10000 <dbl>, log_pri_length_15000 <dbl>,
# log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
# log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
# log_prisec_length_10000 <dbl>, log_prisec_length_15000 <dbl>,
# log_prisec_length_25000 <dbl>, log_nei_2008_pm25_sum_10000 <dbl>,
# log_nei_2008_pm25_sum_15000 <dbl>, log_nei_2008_pm25_sum_25000 <dbl>,
# log_nei_2008_pm10_sum_10000 <dbl>, log_nei_2008_pm10_sum_15000 <dbl>,
# log_nei_2008_pm10_sum_25000 <dbl>, popdens_county <dbl>,
# popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>, hs <dbl>, somecollege <dbl>,
# associate <dbl>, bachelor <dbl>, grad <dbl>, pov <dbl>, hs_orless <dbl>,
# urc2013 <dbl>, urc2006 <dbl>, aod <dbl>
There were in contrast five monitors for the city of Baltimore, despite the fact that if we take a look at the land area and population of the counties for Baltimore City and Albuquerque, we can see that they had very similar land area and populations.
pm %>%
dplyr::filter(city == "Baltimore") %>%
select(county_area:county_pop)
# A tibble: 5 x 2
county_area county_pop
<dbl> <dbl>
1 209643241 620961
2 209643241 620961
3 209643241 620961
4 209643241 620961
5 209643241 620961
pm %>%
dplyr::filter(city == "Albuquerque") %>%
select(county_area:county_pop)
# A tibble: 2 x 2
county_area county_pop
<dbl> <dbl>
1 3006530549 662564
2 3006530549 662564
In fact, the county containing Albuerque had a larger population. Thus the measurements for Albuquerque were not as thorough as they were for Baltimore.
This may be due to the fact that the monitor values were lower in Albuquerque. It is interesting to note here that the CMAQ values are quite similar for both cities.
Evaluate correlation
In prediction analyses, it is also useful to evaluate if any of the variables are correlated. Why should we care about this?
If we are using a linear regression to model our data, then we might run into a problem called multicollinearity which can lead us to misinterpret what is really predictive of our outcome variable. This phenomenon occurs when the predictor variables actually predict one another. See this case study for a deeper explanation about this.
Another reason we should look out for correlation is that we don’t want to include redundant variables. This can add unnecessary noise to our algorithm causing a reduction in prediction accuracy and it can cause our algorithm to be unnecessarily slower. Finally, it can also make it difficult to interpret what variables are actually predictive.
Intuitively we can expect some of our variables to be correlated.
Let’s first take a look at all of our numeric variables with thecorrplot package: The corrplot package is another option to look at correlation among possible predictors, and particularly useful if we have many predictors.
First, we calculate the Pearson correlation coefficients between all features pairwise using the cor() function of the stats package (which is loaded automatically). Then we use the corrplot::corrplot() function.
PM_cor <- cor(pm %>% dplyr::select_if(is.numeric))
corrplot::corrplot(PM_cor, tl.cex = 0.5)
The tl.cex = 0.5 argument controls the size of the text label.
We can also plot the absolute value of the Pearson correlation coefficients using the abs() function from base R and change the order of the columns.
corrplot(abs(PM_cor), order = "hclust", tl.cex = 0.5, cl.lim = c(0, 1))

There are several options for ordering the variables. See here for more options. Here we will use the “hclust” option for ordering by hierarchical clustering - which will order the variables by how similar they are to one another.
The cl.lim = c(0, 1) argument limits the color label to be between 0 and 1.
We can see that the development variables (imp) variables are correlated with each other as we might expect. We also see that the road density variables seem to be correlated with each other, and the emission variables seem to be correlated with each other.
Also notice that none of the predictors are highly correlated with our outcome variable (value).
We can take also take a closer look using the ggcorr() function and the ggpairs() function of the GGally package.
To select our variables of interest we can use the select() function with the contains() function of the tidyr package.
First let’s look at the imp/development variables. We can change the default color palette (palette = "RdBu") and add on correlation coefficients to the plot (label = TRUE).
select(pm, contains("imp")) %>%
ggcorr(palette = "RdBu", label = TRUE)

select(pm, contains("imp")) %>%
ggpairs()

Indeed, we can see that imp_a1000 and imp_a500 are highly correlated, as well as imp_a10000, imp_a15000.
Next, let’s take a look at the road density data:
select(pm, contains("pri")) %>%
ggcorr(palette = "RdBu", hjust = .85, size = 3,
layout.exp=2, label = TRUE)

We can see that many of the road density variables are highly correlated with one another, while others are less so.
Finally let’s look at the emission variables.
select(pm, contains("nei")) %>%
ggcorr(palette = "RdBu", hjust = .85, size = 3,
layout.exp=2, label = TRUE)

select(pm, contains("nei")) %>%
ggpairs()

We would also expect the population density data might correlate with some of these variables. Let’s take a look.
pm %>%
select(log_nei_2008_pm25_sum_10000, popdens_county,
log_pri_length_10000, imp_a10000) %>%
ggcorr(palette = "RdBu", hjust = .85, size = 3,
layout.exp=2, label = TRUE)

pm %>%
select(log_nei_2008_pm25_sum_10000, popdens_county,
log_pri_length_10000, imp_a10000, county_pop) %>%
ggpairs()

Interesting, so these variables don’t appear to be highly correlated, therefore we might need variables from each of the categories to predict our monitor PM2.5 pollution values.
Because some variables in our data have extreme values, it might be good to take a log transformation. This can affect our estimates of correlation.
pm %>%
mutate(log_popdens_county= log(popdens_county)) %>%
select(log_nei_2008_pm25_sum_10000, log_popdens_county,
log_pri_length_10000, imp_a10000) %>%
ggcorr(palette = "RdBu", hjust = .85, size = 3,
layout.exp=2, label = TRUE)

pm %>%
mutate(log_popdens_county= log(popdens_county)) %>%
mutate(log_pop_county = log(county_pop)) %>%
select(log_nei_2008_pm25_sum_10000, log_popdens_county,
log_pri_length_10000, imp_a10000, log_pop_county) %>%
ggpairs()

Indeed this increased the correlation, but variables from each of these categories may still prove to be useful for prediction.
Now that we have a sense of what our data are, we can get started with building a machine learning model to predict air pollution.
Exercise
Suppose we have a dataframe called mydata. There are five variables in this dataframe: var1, var2, var3, var4, and var5. Try to come up with the code for creating the plot called myplot. This plot visualizes correlations between variables. (Hint: start from mydata and use a function from the GGally package)
Data Visualization
Our main question for this case study was:
Can we predict annual average air pollution concentrations at the granularity of zip code regional levels using predictors such as data about population density, urbanization, road density, as well as, satellite pollution data and chemical modeling data?
Thus far, we have built a machine learning (ML) model to predict fine particulate matter air pollution levels based on our predictor variables (or features).
Now, let’s make a plot of our predicted outcome values (\(\hat{Y}\)) and actual outcome values \(Y\) we observed.
First, let’s start by making a plot of our monitors. To do this, we will use the following packages to create a map of the US:
sf - the simple features package helps to convert geographical coordinates into geometry variables which are useful for making 2D plots
maps - this package contains geographical outlines and plotting functions to create plots with maps
rnaturalearth- this allows for easy interaction with map data from Natural Earth which is a public domain map dataset
rgeos - this package interfaces with the Geometry Engine-Open Source (GEOS) which is also helpful for coordinate conversion
We will start with getting an outline of the US with the ne_countries() function of the rnaturalearth package which will return polygons of the countries in the Natural Earth dataset.
world <- ne_countries(scale = "medium", returnclass = "sf")
glimpse(world)
Rows: 241
Columns: 64
$ scalerank <int> 3, 1, 1, 1, 1, 3, 3, 1, 1, 1, 3, 1, 5, 3, 1, 1, 1, 1, 1,...
$ featurecla <chr> "Admin-0 country", "Admin-0 country", "Admin-0 country",...
$ labelrank <dbl> 5, 3, 3, 6, 6, 6, 6, 4, 2, 6, 4, 4, 5, 6, 6, 2, 4, 5, 6,...
$ sovereignt <chr> "Netherlands", "Afghanistan", "Angola", "United Kingdom"...
$ sov_a3 <chr> "NL1", "AFG", "AGO", "GB1", "ALB", "FI1", "AND", "ARE", ...
$ adm0_dif <dbl> 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0,...
$ level <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
$ type <chr> "Country", "Sovereign country", "Sovereign country", "De...
$ admin <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ adm0_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
$ geou_dif <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ geounit <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ gu_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
$ su_dif <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ subunit <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ su_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
$ brk_diff <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ name <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ name_long <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ brk_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
$ brk_name <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ brk_group <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ abbrev <chr> "Aruba", "Afg.", "Ang.", "Ang.", "Alb.", "Aland", "And."...
$ postal <chr> "AW", "AF", "AO", "AI", "AL", "AI", "AND", "AE", "AR", "...
$ formal_en <chr> "Aruba", "Islamic State of Afghanistan", "People's Repub...
$ formal_fr <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ note_adm0 <chr> "Neth.", NA, NA, "U.K.", NA, "Fin.", NA, NA, NA, NA, "U....
$ note_brk <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Multiple cl...
$ name_sort <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ name_alt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ mapcolor7 <dbl> 4, 5, 3, 6, 1, 4, 1, 2, 3, 3, 4, 4, 1, 7, 2, 1, 3, 1, 2,...
$ mapcolor8 <dbl> 2, 6, 2, 6, 4, 1, 4, 1, 1, 1, 5, 5, 2, 5, 2, 2, 1, 6, 2,...
$ mapcolor9 <dbl> 2, 8, 6, 6, 1, 4, 1, 3, 3, 2, 1, 1, 2, 9, 5, 2, 3, 5, 5,...
$ mapcolor13 <dbl> 9, 7, 1, 3, 6, 6, 8, 3, 13, 10, 1, NA, 7, 11, 5, 7, 4, 8...
$ pop_est <dbl> 103065, 28400000, 12799293, 14436, 3639453, 27153, 83888...
$ gdp_md_est <dbl> 2258.0, 22270.0, 110300.0, 108.9, 21810.0, 1563.0, 3660....
$ pop_year <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ lastcensus <dbl> 2010, 1979, 1970, NA, 2001, NA, 1989, 2010, 2010, 2001, ...
$ gdp_year <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ economy <chr> "6. Developing region", "7. Least developed region", "7....
$ income_grp <chr> "2. High income: nonOECD", "5. Low income", "3. Upper mi...
$ wikipedia <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ fips_10 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ iso_a2 <chr> "AW", "AF", "AO", "AI", "AL", "AX", "AD", "AE", "AR", "A...
$ iso_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", ...
$ iso_n3 <chr> "533", "004", "024", "660", "008", "248", "020", "784", ...
$ un_a3 <chr> "533", "004", "024", "660", "008", "248", "020", "784", ...
$ wb_a2 <chr> "AW", "AF", "AO", NA, "AL", NA, "AD", "AE", "AR", "AM", ...
$ wb_a3 <chr> "ABW", "AFG", "AGO", NA, "ALB", NA, "ADO", "ARE", "ARG",...
$ woe_id <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ adm0_a3_is <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", ...
$ adm0_a3_us <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
$ adm0_a3_un <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ adm0_a3_wb <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ continent <chr> "North America", "Asia", "Africa", "North America", "Eur...
$ region_un <chr> "Americas", "Asia", "Africa", "Americas", "Europe", "Eur...
$ subregion <chr> "Caribbean", "Southern Asia", "Middle Africa", "Caribbea...
$ region_wb <chr> "Latin America & Caribbean", "South Asia", "Sub-Saharan ...
$ name_len <dbl> 5, 11, 6, 8, 7, 5, 7, 20, 9, 7, 14, 10, 23, 22, 17, 9, 7...
$ long_len <dbl> 5, 11, 6, 8, 7, 13, 7, 20, 9, 7, 14, 10, 27, 35, 19, 9, ...
$ abbrev_len <dbl> 5, 4, 4, 4, 4, 5, 4, 6, 4, 4, 9, 4, 7, 10, 6, 4, 5, 4, 4...
$ tiny <dbl> 4, NA, NA, NA, NA, 5, 5, NA, NA, NA, 3, NA, NA, 2, 4, NA...
$ homepart <dbl> NA, 1, 1, NA, 1, NA, 1, 1, 1, 1, NA, 1, NA, NA, 1, 1, 1,...
$ geometry <MULTIPOLYGON [°]> MULTIPOLYGON (((-69.89912 1..., MULTIPOLYGO...
Here you can see the data about the countries in the world. Notice the geometry variable. This is used to create the outlines that we want.
Now we can use the geom_sf() function of the ggplot2 package to create a visual of simple feature (the geometry coordinates found in the geometry variable).
ggplot(data = world) +
geom_sf()

So now we can see that we have outlines of all the countries in the world.
We want to limit this just to the coordinates for the US. We will do this based on the coordinates we found on Wikipedia. According to this link, these are the latitude and longitude bounds of the continental US:
- top = 49.3457868 # north lat
- left = -124.7844079 # west long
- right = -66.9513812 # east long
- bottom = 24.7433195 # south lat
ggplot(data = world) +
geom_sf() +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE)
Now we just have a plot that is mostly limited to the outline of the US.
Now we will use the geom_point() function of the ggplot package to add scatter plot on top of the map. We want to show where the monitors are located based on the latitude and longitude values in the data.
ggplot(data = world) +
geom_sf() +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE)+
geom_point(data = pm, aes(x = lon, y = lat), size = 2,
shape = 23, fill = "darkred")
Nice!
Now let’s add county lines.
County graphical data is available from the maps package. The sf package which again is short for simple features creates a data frame about this graphical data so that we can work with it.
counties <-
sf::st_as_sf(maps::map("county", plot = FALSE,
fill = TRUE))
counties
Simple feature collection with 3076 features and 1 field
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -124.6813 ymin: 25.12993 xmax: -67.00742 ymax: 49.38323
geographic CRS: WGS 84
First 10 features:
ID geom
1 alabama,autauga MULTIPOLYGON (((-86.50517 3...
2 alabama,baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama,barbour MULTIPOLYGON (((-85.42801 3...
4 alabama,bibb MULTIPOLYGON (((-87.02083 3...
5 alabama,blount MULTIPOLYGON (((-86.9578 33...
6 alabama,bullock MULTIPOLYGON (((-85.66866 3...
7 alabama,butler MULTIPOLYGON (((-86.8604 31...
8 alabama,calhoun MULTIPOLYGON (((-85.74313 3...
9 alabama,chambers MULTIPOLYGON (((-85.59416 3...
10 alabama,cherokee MULTIPOLYGON (((-85.46812 3...
Now we will use this data within the geom_sf() function to add this to our plot. We will also add a title using the ggtitle() function, as well as remove axis ticks and titles using the theme() function of the ggplot2 package.
monitors <- ggplot(data = world) +
geom_sf(data = counties, fill = NA, color = gray(.5))+
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE) +
geom_point(data = pm, aes(x = lon, y = lat), size = 2,
shape = 23, fill = "darkred") +
ggtitle("Monitor Locations") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
monitors

Great!
Now, let’s add a fill at the county-level for the true monitor values of air pollution.
First, we need to get the county map data that we just got and our air pollution data to have similarly formatted county names so that we can combine the datasets together.
We can see that in the county data the counties are listed after the state name and a comma. In addition they are all lower case.
Simple feature collection with 6 features and 1 field
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -88.01778 ymin: 30.24071 xmax: -85.06131 ymax: 34.2686
geographic CRS: WGS 84
ID geom
1 alabama,autauga MULTIPOLYGON (((-86.50517 3...
2 alabama,baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama,barbour MULTIPOLYGON (((-85.42801 3...
4 alabama,bibb MULTIPOLYGON (((-87.02083 3...
5 alabama,blount MULTIPOLYGON (((-86.9578 33...
6 alabama,bullock MULTIPOLYGON (((-85.66866 3...
In contrast, our air pollution pm data shows counties as titles with the first letter as upper case.
dplyr::pull(pm, county) %>%
head()
[1] "Baldwin" "Clay" "Colbert" "DeKalb" "Etowah" "Houston"
We can use the separate() function of the tidyr package to separate the ID variable of our counties data into two variables based on the comma as a separator.
counties %<>%
tidyr::separate(ID, into = c("state", "county"), sep = ",")
head(counties)
Simple feature collection with 6 features and 2 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -88.01778 ymin: 30.24071 xmax: -85.06131 ymax: 34.2686
geographic CRS: WGS 84
state county geom
1 alabama autauga MULTIPOLYGON (((-86.50517 3...
2 alabama baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama barbour MULTIPOLYGON (((-85.42801 3...
4 alabama bibb MULTIPOLYGON (((-87.02083 3...
5 alabama blount MULTIPOLYGON (((-86.9578 33...
6 alabama bullock MULTIPOLYGON (((-85.66866 3...
Now we just need to make these names in the new county variable of the counties data to be in title format. We can use the str_to_title() function of the stringr package to do this.
counties[["county"]] <- stringr::str_to_title(counties[["county"]])
Great! Now the county information is the same for the counties and pm data.
We can use the inner_join() function of the dplyr package to join the datasets together based on the county variables in each. This function will keep all rows that are in both datasets.
map_data <-dplyr::inner_join(counties, pm, by = "county")
glimpse(map_data)
Rows: 3,926
Columns: 52
$ state.x <chr> "alabama", "alabama", "alabama", "alaba...
$ county <chr> "Baldwin", "Bibb", "Bibb", "Butler", "B...
$ id <fct> 1003.001, 13021.0007, 13021.0012, 39017...
$ value <dbl> 9.597647, 12.253134, 12.233673, 13.9180...
$ fips <fct> 1003, 13021, 13021, 39017, 39017, 13059...
$ lat <dbl> 30.49800, 32.77746, 32.80541, 39.49380,...
$ lon <dbl> -87.88141, -83.64110, -83.54352, -84.35...
$ state.y <chr> "Alabama", "Georgia", "Georgia", "Ohio"...
$ city <chr> "In a city", "In a city", "In a city", ...
$ CMAQ <dbl> 8.098836, 11.716801, 11.716801, 11.3219...
$ zcta <fct> 36532, 31206, 31020, 45044, 45015, 3060...
$ zcta_area <dbl> 190980522, 72325015, 276913325, 9874681...
$ zcta_pop <dbl> 27829, 29072, 2541, 52822, 12038, 39952...
$ imp_a500 <dbl> 0.01730104, 35.64359862, 0.28200692, 27...
$ imp_a1000 <dbl> 1.4096021, 24.4824827, 0.2973616, 28.28...
$ imp_a5000 <dbl> 3.3360118, 8.7317283, 2.4691097, 22.697...
$ imp_a10000 <dbl> 1.9879187, 9.1999720, 1.9873487, 11.901...
$ imp_a15000 <dbl> 1.4386207, 6.4619966, 3.6435089, 8.4052...
$ county_area <dbl> 4117521611, 646879637, 646879637, 12096...
$ county_pop <dbl> 182265, 155547, 155547, 368130, 368130,...
$ log_dist_to_prisec <dbl> 4.648181, 7.635438, 7.576493, 5.959728,...
$ log_pri_length_5000 <dbl> 8.517193, 10.215058, 10.659655, 9.74773...
$ log_pri_length_10000 <dbl> 9.210340, 12.116408, 11.653566, 10.7343...
$ log_pri_length_15000 <dbl> 9.630228, 12.591833, 12.313347, 11.1728...
$ log_pri_length_25000 <dbl> 11.32735, 13.12475, 13.02383, 12.14238,...
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 6.214608, 8.104926,...
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 7.600902, 9.180109,...
$ log_prisec_length_5000 <dbl> 10.81504, 11.61283, 11.34202, 11.63677,...
$ log_prisec_length_10000 <dbl> 11.88680, 13.23991, 12.47152, 12.62117,...
$ log_prisec_length_15000 <dbl> 12.20572, 13.74532, 13.37704, 13.26170,...
$ log_prisec_length_25000 <dbl> 13.41395, 14.28483, 14.25295, 14.16745,...
$ log_nei_2008_pm25_sum_10000 <dbl> 0.3180354, 5.5380414, 0.1972941, 7.2307...
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967359, 5.538041, 5.536822, 7.408732,...
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 5.986616, 5.986572, 7.538614,...
$ log_nei_2008_pm10_sum_10000 <dbl> 1.3558851, 5.6035407, 0.9849611, 7.2785...
$ log_nei_2008_pm10_sum_15000 <dbl> 2.2678341, 5.6035407, 5.5971561, 7.4899...
$ log_nei_2008_pm10_sum_25000 <dbl> 5.6287284, 6.0302900, 6.0347672, 7.6330...
$ popdens_county <dbl> 44.265706, 240.457407, 240.457407, 304....
$ popdens_zcta <dbl> 145.716431, 401.963277, 9.176156, 534.9...
$ nohs <dbl> 3.300, 8.700, 6.800, 1.300, 3.500, 3.80...
$ somehs <dbl> 4.900, 24.700, 17.500, 3.300, 7.700, 6....
$ hs <dbl> 25.10, 32.60, 46.60, 33.40, 33.40, 17.8...
$ somecollege <dbl> 19.7, 12.9, 18.7, 23.0, 23.2, 16.1, 18....
$ associate <dbl> 8.200, 4.800, 5.000, 8.700, 8.100, 5.10...
$ bachelor <dbl> 25.30, 8.90, 4.00, 22.20, 16.20, 25.40,...
$ grad <dbl> 13.50, 7.30, 1.30, 8.10, 7.90, 25.00, 3...
$ pov <dbl> 6.100, 38.800, 26.800, 0.900, 6.900, 12...
$ hs_orless <dbl> 33.30, 66.00, 70.90, 38.00, 44.60, 28.4...
$ urc2013 <dbl> 4, 4, 4, 2, 2, 4, 6, 2, 4, 1, 1, 1, 3, ...
$ urc2006 <dbl> 5, 4, 4, 2, 2, 4, 6, 2, 4, 1, 1, 1, 3, ...
$ aod <dbl> 37.36364, 36.25000, 30.45455, 48.36364,...
$ geom <MULTIPOLYGON [°]> MULTIPOLYGON (((-87.93757 ...
Nice! we can see that we have add a geom variable to the pm data.
Now we can use this to color the counties in our plot based on the value variable of our pm data, which you may recall is the actual monitor data for fine particulate air pollution at each monitor.
WE can do so using the scale_fill_gradientn() function of the ggplot2 package which creates color gradient based on a variable. In this case it is the variable that was specified as the fill in the aes function of the geom_sf() function. We specified that it would be the value variable of the pm data.
This scale_fill_gradientn() function also allows you to specify the colors, what to do about NA values (should they be a specific color or transparent) and the breaks, limits, labels and name/title on the legend for the color gradient.
truth <-ggplot(data = world) +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50), expand = FALSE)+
geom_sf(data = map_data, aes(fill = value)) +
scale_fill_gradientn(colours=topo.colors(7), na.value = "transparent",
breaks=c(0,10,20),labels=c(0,10,20),
limits=c(0,23.5), name = "PM ug/m3") +
ggtitle("True PM 2.5 levels") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
truth
Nice!
Now let’s do the same with our predicted outcome values.
Let’s grab both the testing and training predicted outcome values so that we have as much data as possible.
First we need to fit our training data with our final model to be able to get the predictions for the monitors included in the training set. We did this using the last_fit() function, but the output of this makes it difficult to grab the predicted values for the training data, and it is also difficult to get the id variables for the testing data.
Thus we will use the parsnip fit() and predict() functions of the parsnip package to do this like so:
Question Opportunity
Why do we not need pre-processed data?
Click here to reveal the answer.
Since we are using a workflow, the data will be pre-processed when it is fit as well.
RF_final_train_fit <- parsnip::fit(RF_tuned_wflow, data = train_pm)
RF_final_test_fit <- parsnip::fit(RF_tuned_wflow, data = test_pm)
values_pred_train <-
predict(RF_final_train_fit, train_pm) %>%
bind_cols(train_pm %>% select(value, fips, county, id))
values_pred_train
# A tibble: 584 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 10.0 9.60 1003 Baldwin 1003.001
2 10.9 10.8 1027 Clay 1027.0001
3 11.5 11.2 1033 Colbert 1033.1002
4 12.1 12.4 1055 Etowah 1055.001
5 10.7 10.5 1069 Houston 1069.0003
6 14.7 15.6 1073 Jefferson 1073.0023
7 12.2 12.4 1073 Jefferson 1073.1005
8 11.0 11.1 1073 Jefferson 1073.1009
9 13.8 14.6 1073 Jefferson 1073.2003
10 11.8 12.0 1073 Jefferson 1073.5002
# ... with 574 more rows
values_pred_test <-
predict(RF_final_test_fit, test_pm) %>%
bind_cols(test_pm %>% select(value, fips, county, id))
values_pred_test
# A tibble: 292 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 11.6 11.7 1049 DeKalb 1049.1003
2 12.6 13.1 1073 Jefferson 1073.101
3 12.3 12.2 1073 Jefferson 1073.2006
4 12.0 12.2 1089 Madison 1089.0014
5 11.6 11.4 1103 Morgan 1103.0011
6 12.3 12.2 1121 Talladega 1121.0002
7 11.0 10.9 4013 Maricopa 4013.4003
8 10.5 10.6 4021 Pinal 4021.0001
9 12.1 14.1 4023 Santa Cruz 4023.0004
10 7.33 5.83 4025 Yavapai 4025.2002
# ... with 282 more rows
Now we can combine this data for the predictions for all monitors using the bind_rows() function of the dplyr package, which will essentially append the second dataset to the first.
all_pred <- bind_rows(values_pred_test, values_pred_train)
all_pred
# A tibble: 876 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 11.6 11.7 1049 DeKalb 1049.1003
2 12.6 13.1 1073 Jefferson 1073.101
3 12.3 12.2 1073 Jefferson 1073.2006
4 12.0 12.2 1089 Madison 1089.0014
5 11.6 11.4 1103 Morgan 1103.0011
6 12.3 12.2 1121 Talladega 1121.0002
7 11.0 10.9 4013 Maricopa 4013.4003
8 10.5 10.6 4021 Pinal 4021.0001
9 12.1 14.1 4023 Santa Cruz 4023.0004
10 7.33 5.83 4025 Yavapai 4025.2002
# ... with 866 more rows
Great! as we can see there are 876 values like we would expect for all of the monitors. We can use the county variable to combine this with the counties data like we did with the pm data previously so that we can use the value variable as a color scheme for our map.
map_data <- inner_join(counties, all_pred, by = "county")
pred <- ggplot(data = world) +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE) +
geom_sf(data = map_data, aes(fill = .pred)) +
scale_fill_gradientn(colours=topo.colors(7), na.value = "transparent",
breaks=c(0,10,20),labels=c(0,10,20),
limits=c(0,23.5), name = "PM ug/m3") +
ggtitle("Predicted PM 2.5 levels")+
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
pred

Now we will use the patchwork package to combine our last two plots. This allows us to combine plots using the + or the / . The + will place plots side by side and the / will place plots top to bottom.
Now let’s just combine the truth plot and the prediction plots together:

We can see that the predicted fine particle air pollution values in (ug/m3) are quite similar to the true values measured by the actual gravimetric monitors. We can also see that southern California has some large counties with worse pollution (as they are yellow and thus have much higher particulate matter levels).
Let’s add some text to our plot to explain it a bit more. We can do so using the plot_annotation() function of the patchwork package. The theme argument of this function takes the same theme information using the theme() function of the ggplot2 package as when creating ggplot2plots.
(truth/pred) + plot_annotation(title = "Machine Learning Methods Allow for Prediction of Air Pollution", subtitle = "A random forest model predicts true monitored levels of fine particulate matter (PM 2.5) air pollution based on\ndata about population density and other predictors reasonably well, thus suggesting that we can predict levels\nof pollution in places with poor monitoring", theme = theme(plot.title = element_text(size =12, face = "bold"), plot.subtitle = element_text(size = 8)))

LS0tDQp0aXRsZTogIk9wZW4gQ2FzZSBTdHVkaWVzOiBQcmVkaWN0aW5nIEFubnVhbCBBaXIgUG9sbHV0aW9uIg0KY3NzOiBzdHlsZS5jc3MNCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBpbmNsdWRlczoNCiAgICAgIGluX2hlYWRlcjogaGVhZGVyLmh0bWwNCiAgICBzZWxmX2NvbnRhaW5lZDogeWVzDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0aGVtZTogY29zbW8NCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQotLS0NCjxzdHlsZT4NCiNUT0Mgew0KICBiYWNrZ3JvdW5kOiB1cmwoImh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9pbWcvaWNvbi1iYWhpLnBuZyIpOw0KICBiYWNrZ3JvdW5kLXNpemU6IGNvbnRhaW47DQogIHBhZGRpbmctdG9wOiAyNDBweCAhaW1wb3J0YW50Ow0KICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0Ow0KfQ0KPC9zdHlsZT4NCg0KPCEtLSBPcGVuIGFsbCBsaW5rcyBpbiBuZXcgdGFiLS0+ICANCjxiYXNlIHRhcmdldD0iX2JsYW5rIi8+IA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGhlcmUpDQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIsIG91dC53aWR0aCA9ICc5MCUnKQ0KYGBgDQoNCg0KIyMjIyB7Lm91dGxpbmUgfQ0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjgwMCBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAibWFpbl9wbG90X21hcHMucG5nIikpDQpgYGANCg0KIyMjIw0KDQojIyMjIHsuZGlzY2xhaW1lcl9ibG9ja30NCg0KKipEaXNjbGFpbWVyKio6IFRoZSBwdXJwb3NlIG9mIHRoZSBbT3BlbiBDYXNlIFN0dWRpZXNdKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pbyl7dGFyZ2V0PSJfYmxhbmsifSBwcm9qZWN0IGlzICoqdG8gZGVtb25zdHJhdGUgdGhlIHVzZSBvZiB2YXJpb3VzIGRhdGEgc2NpZW5jZSBtZXRob2RzLCB0b29scywgYW5kIHNvZnR3YXJlIGluIHRoZSBjb250ZXh0IG9mIG1lc3N5LCByZWFsLXdvcmxkIGRhdGEqKi4gQSBnaXZlbiBjYXNlIHN0dWR5IGRvZXMgbm90IGNvdmVyIGFsbCBhc3BlY3RzIG9mIHRoZSByZXNlYXJjaCBwcm9jZXNzLCBpcyBub3QgY2xhaW1pbmcgdG8gYmUgdGhlIG1vc3QgYXBwcm9wcmlhdGUgd2F5IHRvIGFuYWx5emUgYSBnaXZlbiBkYXRhIHNldCwgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBpbiB0aGUgY29udGV4dCBvZiBtYWtpbmcgcG9saWN5IGRlY2lzaW9ucyB3aXRob3V0IGV4dGVybmFsIGNvbnN1bHRhdGlvbiBmcm9tIHNjaWVudGlmaWMgZXhwZXJ0cy4gDQoNCiMjIyMNCg0KIyMjIyB7LmxpY2Vuc2VfYmxvY2t9DQoNClRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBbKENDIEJZLU5DIDMuMCldKGh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvdXMvKXt0YXJnZXQ9Il9ibGFuayJ9IFVuaXRlZCBTdGF0ZXMgTGljZW5zZS4NCg0KIyMjIw0KDQojIyMjIHsucmVmZXJlbmNlX2Jsb2NrfQ0KDQpUbyBjaXRlIHRoaXMgY2FzZSBzdHVkeSBwbGVhc2UgdXNlOg0KDQpXcmlnaHQsIENhcnJpZSBhbmQgSmFnZXIsIExlYWggYW5kIFRhdWIsIE1hcmdhcmV0IGFuZCBIaWNrcywgU3RlcGhhbmllLiAoMjAyMCkuIFtodHRwczovL2dpdGh1Yi5jb20vL29wZW5jYXNlc3R1ZGllcy9vY3MtYnAtYWlyLXBvbGx1dGlvbl0oaHR0cHM6Ly9naXRodWIuY29tLy9vcGVuY2FzZXN0dWRpZXMvb2NzLWJwLWFpci1wb2xsdXRpb24vKS4gUHJlZGljdGluZyBBbm51YWwgQWlyIFBvbGx1dGlvbiAoVmVyc2lvbiB2MS4wLjApLg0KDQojIyMjDQoNClRvIGFjY2VzcyB0aGUgR2l0SHViIFJlcG9zaXRvcnkgZm9yIHRoaXMgY2FzZSBzdHVkeSBzZWUgaGVyZTogaHR0cHM6Ly9naXRodWIuY29tL29wZW5jYXNlc3R1ZGllcy9vY3MtYnAtYWlyLXBvbGx1dGlvbi4NCg0KVGhpcyBjYXNlIHN0dWR5IGlzIHBhcnQgb2YgYSBzZXJpZXMgb2YgcHVibGljIGhlYWx0aCBjYXNlIHN0dWRpZXMgZm9yIHRoZSBbQmxvb21iZXJnIEFtZXJpY2FuIEhlYWx0aCAgSW5pdGlhdGl2ZV0oaHR0cHM6Ly9hbWVyaWNhbmhlYWx0aC5qaHUuZWR1L29wZW4tY2FzZS1zdHVkaWVzKS4NCg0KIyAqKk1vdGl2YXRpb24qKg0KKioqDQpBIHZhcmlldHkgb2YgZGlmZmVyZW50IHNvdXJjZXMgY29udHJpYnV0ZSBkaWZmZXJlbnQgdHlwZXMgb2YgcG9sbHV0YW50cyB0byB3aGF0IHdlIGNhbGwgYWlyIHBvbGx1dGlvbi4gDQoNClNvbWUgc291cmNlcyBhcmUgbmF0dXJhbCB3aGlsZSBvdGhlcnMgYXJlIGFudGhyb3BvZ2VuaWMgKGh1bWFuIGRlcml2ZWQpOg0KDQo8cCBhbGlnbj0iY2VudGVyIj4NCjxpbWcgd2lkdGg9IjYwMCIgc3JjPSJodHRwczovL3d3dy5ucHMuZ292L3N1YmplY3RzL2Fpci9pbWFnZXMvU291cmNlc19HcmFwaGljX0h1Z2UuanBnP21heHdpZHRoPTEyMDAmbWF4aGVpZ2h0PTEyMDAmYXV0b3JvdGF0ZT1mYWxzZSI+DQo8L3A+DQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS91cmw/c2E9aSZ1cmw9aHR0cHMlM0ElMkYlMkZ3d3cubnBzLmdvdiUyRnN1YmplY3RzJTJGYWlyJTJGc291cmNlcy5odG0mcHNpZz1BT3ZWYXcydjdBVnhTRjhaU0FQRWhOdWRWdGJOJnVzdD0xNTg1NzcwOTY2MjE3MDAwJnNvdXJjZT1pbWFnZXMmY2Q9dmZlJnZlZD0wQ0FJUWpSeHFGd29UQ1BETjY2cV94ZWdDRlFBQUFBQWRBQUFBQUJBRCl7dGFyZ2V0PSJfYmxhbmsifQ0KDQojIyMgTWFqb3IgdHlwZXMgb2YgYWlyIHBvbGx1dGFudHMNCg0KMSkgKipHYXNlb3VzKiogLSBDYXJib24gTW9ub3hpZGUgKENPKSwgT3pvbmUgKE9+M34pLCBOaXRyb2dlbiBPeGlkZXMoTk8sIE5PfjJ+KSwgU3VsZnVyIERpb3hpZGUgKFNPfjJ+KQ0KMikgKipQYXJ0aWN1bGF0ZSoqIC0gc21hbGwgbGlxdWlkcyBhbmQgc29saWRzIHN1c3BlbmRlZCBpbiB0aGUgYWlyIChpbmNsdWRlcyBsZWFkLSBjYW4gaW5jbHVkZSBjZXJ0YWluIHR5cGVzIG9mIGR1c3QpDQozKSAqKkR1c3QqKiAtIHNtYWxsIHNvbGlkcyAobGFyZ2VyIHRoYW4gcGFydGljdWxhdGVzKSB0aGF0IGNhbiBiZSBzdXNwZW5kZWQgaW4gdGhlIGFpciBmb3Igc29tZSB0aW1lIGJ1dCBldmVudHVhbGx5IHNldHRsZQ0KNCkgKipCaW9sb2dpY2FsKiogLSBwb2xsZW4sIGJhY3RlcmlhLCB2aXJ1c2VzLCBtb2xkIHNwb3Jlcw0KDQpTZWUgW2hlcmVdKGh0dHA6Ly93d3cucmVkbG9nZW52LmNvbS93b3JrZXItc2FmZXR5L3BhcnQtMS1kdXN0LWFuZC1wYXJ0aWN1bGF0ZS1tYXR0ZXIpIGZvciBtb3JlIGRldGFpbCBvbiB0aGUgdHlwZXMgb2YgcG9sbHV0YW50cyBpbiB0aGUgYWlyLg0KDQoNCiMjIyBQYXJ0aWN1bGF0ZSBwb2xsdXRpb24gDQoNCkFpciBwb2xsdXRpb24gcGFydGljdWxhdGVzIGFyZSBnZW5lcmFsbHkgZGVzY3JpYmVkIGJ5IHRoZWlyICoqc2l6ZSoqLg0KDQpUaGVyZSBhcmUgMyBtYWpvciBjYXRlZ29yaWVzOg0KDQoxKSAqKkxhcmdlIENvYXJzZSoqIFBhcnRpY3VsYXRlIE1hdHRlciAtIGhhcyBkaWFtZXRlciBvZiA+MTAgbWljcm9tZXRlcnMgKDEwIMK1bSkgDQoNCjIpICoqQ29hcnNlKiogUGFydGljdWxhdGUgTWF0dGVyIChjYWxsZWQgKipQTX4xMC0yLjV+KiopIC0gaGFzIGRpYW1ldGVyIG9mIGJldHdlZW4gMi41IMK1bSBhbmQgMTAgwrVtDQoNCjMpICoqRmluZSoqIFBhcnRpY3VsYXRlIE1hdHRlciAoY2FsbGVkICoqUE1+Mi41fioqKSAtIGhhcyBkaWFtZXRlciBvZiA8IDIuNSDCtW0gDQoNCioqUE1+MTB+KiogaW5jbHVkZXMgYW55IHBhcnRpY3VsYXRlIG1hdHRlciA8MTAgwrVtIChib3RoIGNvYXJzZSBhbmQgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIpDQoNCkhlcmUgeW91IGNhbiBzZWUgaG93IHRoZXNlIHNpemVzIGNvbXBhcmUgd2l0aCBhIGh1bWFuIGhhaXI6DQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0gIjYwMCBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAicG0yLjVfc2NhbGVfZ3JhcGhpYy1jb2xvcl8yLmpwZyIpKQ0KYGBgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuZXBhLmdvdi9wbS1wb2xsdXRpb24vcGFydGljdWxhdGUtbWF0dGVyLXBtLWJhc2ljcyl7dGFyZ2V0PSJfYmxhbmsifQ0KDQo8IS0tIDxwIGFsaWduPSJjZW50ZXIiPiAtLT4NCjwhLS0gICA8aW1nIHdpZHRoPSI1MDAiIHNyYz0iaHR0cHM6Ly93d3cuc2Vuc2lyaW9uLmNvbS9pbWFnZXMvc2Vuc2lyaW9uLXNwZWNpYWxpc3QtYXJ0aWNsZS1maWd1cmUtMS1jZGQ3MC5qcGciPiAtLT4NCjwhLS0gPC9wPiAtLT4NCg0KDQo8dT5UaGUgZm9sbG93aW5nIHBsb3QgYW5kIHRhYmxlIHNob3cgdGhlIHJlbGF0aXZlIHNpemVzIG9mIHRoZXNlIGRpZmZlcmVudCBwb2xsdXRhbnRzIGluIG1pY3JvbWV0ZXJzICjCtW0pOjwvdT4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiODAwIHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJwYXJ0aWN1bGF0ZS1zaXplLWNoYXJ0LnBuZyIpKQ0KYGBgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGFydGljdWxhdGVzKXt0YXJnZXQ9Il9ibGFuayJ9DQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiODAwIHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJwYXJ0aWN1bGF0ZV90eXBlcy5qcGciKSkNCmBgYA0KDQojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmZyb250aWVyc2luLm9yZy9hcnRpY2xlcy8xMC4zMzg5L2ZwdWJoLjIwMjAuMDAwMTQvZnVsbCl7dGFyZ2V0PSJfYmxhbmsifQ0KDQoNCjx1PlRoaXMgdGFibGUgc2hvd3MgaG93IGRlZXBseSBzb21lIG9mIHRoZSBzbWFsbGVyIGZpbmUgcGFydGljbGVzIGNhbiBwZW5ldHJhdGUgd2l0aGluIHRoZSBodW1hbiBib2R5OjwvdT4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiODAwIHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJzaXplcy5qcGciKSkNCmBgYA0KDQojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmZyb250aWVyc2luLm9yZy9hcnRpY2xlcy8xMC4zMzg5L2ZwdWJoLjIwMjAuMDAwMTQvZnVsbCl7dGFyZ2V0PSJfYmxhbmsifQ0KDQoNCiMjIyBOZWdhdGl2ZSBpbXBhY3Qgb2YgcGFydGljdWxhdGUgZXhwb3N1cmUgb24gaGVhbHRoIA0KDQpFeHBvc3VyZSB0byBhaXIgcG9sbHV0aW9uIGlzIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgcmF0ZXMgb2YgW21vcnRhbGl0eV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNTc4MzE4Ni8pe3RhcmdldD0iX2JsYW5rIn0gaW4gb2xkZXIgYWR1bHRzIGFuZCBpcyBrbm93biB0byBiZSBhIHJpc2sgZmFjdG9yIGZvciBtYW55IGRpc2Vhc2VzIGFuZCBjb25kaXRpb25zIGluY2x1ZGluZyBidXQgbm90IGxpbWl0ZWQgdG86DQoNCjEpIFtBc3RobWFdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzI5MjQzOTM3KXt0YXJnZXQ9Il9ibGFuayJ9IC0gZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAoKipQTX4yLjV+KiopIHdhcyBmb3VuZCB0byBiZSBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIHJhdGVzIG9mIGFzdGhtYSBpbiBjaGlsZHJlbg0KMikgW0luZmxhbW1hdGlvbiBpbiB0eXBlIDEgZGlhYmV0ZXNdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzMxNDE5NzY1KXt0YXJnZXQ9Il9ibGFuayJ9IC0gZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAoKipQTX4yLjV+KiopIGZyb20gdHJhZmZpYy1yZWxhdGVkIGFpciBwb2xsdXRpb24gd2FzIGFzc29jaWF0ZWQgd2l0aCBpbmNyZWFzZWQgbWVhc3VyZXMgb2YgaW5mbGFtbWF0b3J5IG1hcmtlcnMgaW4geW91dGhzIHdpdGggVHlwZSAxIGRpYWJldGVzDQozKSBbTHVuZyBmdW5jdGlvbiBhbmQgZW1waHlzZW1hXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8zMTQwODEzNSl7dGFyZ2V0PSJfYmxhbmsifSAtIGhpZ2hlciBjb25jZW50cmF0aW9ucyBvZiBvem9uZSAoT34zfiksIG5pdHJvZ2VuIG94aWRlcyAoTk9+eH4pLCBibGFjayBjYXJib24sIGFuZCBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlICoqUE1+Mi41fioqICwgYXQgc3R1ZHkgYmFzZWxpbmUgd2VyZSBzaWduaWZpY2FudGx5IGFzc29jaWF0ZWQgd2l0aCBncmVhdGVyIGluY3JlYXNlcyBpbiBwZXJjZW50IGVtcGh5c2VtYSBwZXIgMTAgeWVhcnMgDQo0KSBbTG93IGJpcnRod2VpZ2h0XShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8zMTM4NjY0Myl7dGFyZ2V0PSJfYmxhbmsifSAtIGZpbmUgcGFydGljbGUgZXhwb3N1cmUoKipQTX4yLjV+KiopIHdhcyBhc3NvY2lhdGVkIHdpdGggbG93ZXIgYmlydGggd2VpZ2h0IGluIGZ1bGwtdGVybSBsaXZlIGJpcnRocw0KNSkgW1ZpcmFsIEluZmVjdGlvbl0oaHR0cHM6Ly93d3cudGFuZGZvbmxpbmUuY29tL2RvaS9mdWxsLzEwLjEwODAvMDg5NTgzNzA3MDE2NjU0MzQpe3RhcmdldD0iX2JsYW5rIn0gLSBoaWdoZXIgcmF0ZXMgb2YgaW5mZWN0aW9uIGFuZCBpbmNyZWFzZWQgc2V2ZXJpdHkgb2YgaW5mZWN0aW9uIGFyZSBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIGV4cG9zdXJlcyB0byBwb2xsdXRpb24gbGV2ZWxzIGluY2x1ZGluZyBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlICgqKlBNfjIuNX4qKikNCg0KU2VlIHRoaXMgW3JldmlldyBhcnRpY2xlXShodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcHViaC4yMDIwLjAwMDE0L2Z1bGwpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgc291cmNlcyBvZiBhaXIgcG9sbHV0aW9uIGFuZCB0aGUgaW5mbHVlbmNlIG9mIGFpciBwb2xsdXRpb24gb24gaGVhbHRoLg0KDQojIyMgU3BhcnNlIG1vbml0b3JpbmcgaXMgcHJvYmxlbWF0aWMgZm9yIFB1YmxpYyBIZWFsdGgNCg0KSGlzdG9yaWNhbGx5LCBlcGlkZW1pb2xvZ2ljYWwgc3R1ZGllcyB3b3VsZCBhc3Nlc3MgdGhlIGluZmx1ZW5jZSBvZiBhaXIgcG9sbHV0aW9uIG9uIGhlYWx0aCBvdXRjb21lcyBieSByZWx5aW5nIG9uIGEgbnVtYmVyIG9mIG1vbml0b3JzIGxvY2F0ZWQgYXJvdW5kIHRoZSBjb3VudHJ5LiANCg0KSG93ZXZlciwgYXMgY2FuIGJlIHNlZW4gaW4gdGhlIGZvbGxvd2luZyBmaWd1cmUsIHRoZXNlIG1vbml0b3JzIGFyZSByZWxhdGl2ZWx5IHNwYXJzZSBpbiBjZXJ0YWluIHJlZ2lvbnMgb2YgdGhlIGNvdW50cnkgYW5kIGFyZSBub3QgbmVjZXNzYXJpbHkgbG9jYXRlZCBuZWFyIHBvbGx1dGlvbiBzb3VyY2VzLiBXZSB3aWxsIHNlZSBsYXRlciB3aGVuIHdlIGV2YWx1YXRlIHRoZSBkYXRhLCB0aGF0IGV2ZW4gaW4gY2VydGFpbiByZWxhdGl2ZWx5IGxhcmdlIGNpdGllcyB0aGVyZSBpcyBvbmx5ICBvbmUgbW9uaXRvciENCg0KRnVydGhlcm1vcmUsIGRyYW1hdGljIGRpZmZlcmVuY2VzIGluIHBvbGx1dGlvbiByYXRlcyBjYW4gYmUgc2VlbiBldmVuIHdpdGhpbiB0aGUgc2FtZSBjaXR5LiBJbiBmYWN0LCB0aGUgdGVybSBtaWNyby1lbnZpcm9ubWVudHMgZGVzY3JpYmVzIGVudmlyb25tZW50IHdpdGhpbiBjaXRpZXMgb3IgY291bnRpZXMgd2hpY2ggbWF5IHZhcnkgZ3JlYXRseSBmcm9tIG9uZSBibG9jayB0byBhbm90aGVyLg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9ICI4MDAgcHgifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIm1hcF9vZl9tb25pdG9ycy5qcGciKSkNCmBgYA0KDQojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vZWhqb3VybmFsLmJpb21lZGNlbnRyYWwuY29tL2FydGljbGVzLzEwLjExODYvMTQ3Ni0wNjlYLTEzLTYzKXt0YXJnZXQ9Il9ibGFuayJ9DQoNClRoaXMgbGFjayBvZiBncmFudWxhcml0eSBpbiBhaXIgcG9sbHV0aW9uIG1vbml0b3JpbmcgaGFzIGhpbmRlcmVkIG91ciBhYmlsaXR5IHRvIGRpc2Nlcm4gdGhlIGZ1bGwgaW1wYWN0IG9mIGFpciBwb2xsdXRpb24gb24gaGVhbHRoIGFuZCB0byBpZGVudGlmeSBhdC1yaXNrIGxvY2F0aW9ucy4gDQoNCg0KIyMjIE1hY2hpbmUgbGVhcm5pbmcgb2ZmZXJzIGEgc29sdXRpb24NCg0KQW4gW2FydGljbGVdKGh0dHBzOi8vZWhqb3VybmFsLmJpb21lZGNlbnRyYWwuY29tL2FydGljbGVzLzEwLjExODYvMTQ3Ni0wNjlYLTEzLTYzKXt0YXJnZXQ9Il9ibGFuayJ9IHB1Ymxpc2hlZCBpbiB0aGUgKkVudmlyb25tZW50YWwgSGVhbHRoKiBqb3VybmFsIGRlYWx0IHdpdGggdGhpcyBpc3N1ZSBieSB1c2luZyBkYXRhLCBpbmNsdWRpbmcgcG9wdWxhdGlvbiBkZW5zaXR5LCByb2FkIGRlbnNpdHksIGFtb25nIG90aGVyIGZlYXR1cmVzLCB0byBtb2RlbCBvciBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIGF0IGEgbW9yZSBsb2NhbGl6ZWQgc2NhbGUgdXNpbmcgbWFjaGluZSBsZWFybmluZyAoTUwpIG1ldGhvZHMuIA0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9ICI4MDAgcHgifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInRoZXBhcGVyLnBuZyIpKQ0KYGBgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9laGpvdXJuYWwuYmlvbWVkY2VudHJhbC5jb20vYXJ0aWNsZXMvMTAuMTE4Ni8xNDc2LTA2OVgtMTMtNjMpe3RhcmdldD0iX2JsYW5rIn0NCg0KIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30NCllhbm9za3ksIEouIEQuIGV0IGFsLiBTcGF0aW8tdGVtcG9yYWwgbW9kZWxpbmcgb2YgcGFydGljdWxhdGUgYWlyIHBvbGx1dGlvbiBpbiB0aGUgY29udGVybWlub3VzIFVuaXRlZCBTdGF0ZXMgdXNpbmcgZ2VvZ3JhcGhpYyBhbmQgbWV0ZW9yb2xvZ2ljYWwgcHJlZGljdG9ycy4gKkVudmlyb24gSGVhbHRoKiAxMywgNjMgKDIwMTQpLg0KDQojIyMjDQoNClRoZSBhdXRob3JzIG9mIHRoaXMgYXJ0aWNsZSBzdGF0ZSB0aGF0Og0KDQo+ICJFeHBvc3VyZSB0byBhdG1vc3BoZXJpYyBwYXJ0aWN1bGF0ZSBtYXR0ZXIgKFBNKSByZW1haW5zIGFuIGltcG9ydGFudCBwdWJsaWMgaGVhbHRoIGNvbmNlcm4sIGFsdGhvdWdoIGl0IHJlbWFpbnMgZGlmZmljdWx0IHRvIHF1YW50aWZ5IGFjY3VyYXRlbHkgYWNyb3NzIGxhcmdlIGdlb2dyYXBoaWMgYXJlYXMgd2l0aCBzdWZmaWNpZW50bHkgaGlnaCBzcGF0aWFsIHJlc29sdXRpb24uIFJlY2VudCBlcGlkZW1pb2xvZ2ljIGFuYWx5c2VzIGhhdmUgZGVtb25zdHJhdGVkIHRoZSBpbXBvcnRhbmNlIG9mIHNwYXRpYWxseS0gYW5kIHRlbXBvcmFsbHktcmVzb2x2ZWQgZXhwb3N1cmUgZXN0aW1hdGVzLCB3aGljaCBzaG93IGxhcmdlciBQTS1tZWRpYXRlZCBoZWFsdGggZWZmZWN0cyBhcyBjb21wYXJlZCB0byBuZWFyZXN0IG1vbml0b3Igb3IgY291bnR5LXNwZWNpZmljIGFtYmllbnQgY29uY2VudHJhdGlvbnMuIiANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2Voam91cm5hbC5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2LzE0NzYtMDY5WC0xMy02Myl7dGFyZ2V0PSJfYmxhbmsifQ0KDQpUaGUgYXJ0aWNsZSBhYm92ZSBkZW1vbnN0cmF0ZXMgdGhhdCBtYWNoaW5lIGxlYXJuaW5nIG1ldGhvZHMgY2FuIGJlIHVzZWQgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyB3aGVuIHRyYWRpdGlvbmFsIG1vbml0b3Jpbmcgc3lzdGVtcyBhcmUgbm90IGF2YWlsYWJsZSBpbiBhIHBhcnRpY3VsYXIgYXJlYSBvciB3aGVuIHRoZXJlIGlzIG5vdCBlbm91Z2ggc3BhdGlhbCBncmFudWxhcml0eSB3aXRoIGN1cnJlbnQgbW9uaXRvcmluZyBzeXN0ZW1zLiANCldlIHdpbGwgdXNlIHNpbWlsYXIgbWV0aG9kcyB0byBwcmVkaWN0IGFubnVhbCBhaXIgcG9sbHV0aW9uIGxldmVscyBzcGF0aWFsbHkgd2l0aGluIHRoZSBVUy4NCg0KDQojICoqTWFpbiBRdWVzdGlvbioqDQoqKioNCg0KIyMjIyB7Lm1haW5fcXVlc3Rpb25fYmxvY2t9DQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb246IDwvdT48L2I+DQoNCjEpIENhbiB3ZSBwcmVkaWN0IGFubnVhbCBhdmVyYWdlIGFpciBwb2xsdXRpb24gY29uY2VudHJhdGlvbnMgYXQgdGhlIGdyYW51bGFyaXR5IG9mIHppcCBjb2RlIHJlZ2lvbmFsIGxldmVscyB1c2luZyBwcmVkaWN0b3JzIHN1Y2ggYXMgZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHksIHVyYmFuaXphdGlvbiwgcm9hZCBkZW5zaXR5LCBhcyB3ZWxsIGFzLCBzYXRlbGxpdGUgcG9sbHV0aW9uIGRhdGEgYW5kIGNoZW1pY2FsIG1vZGVsaW5nIGRhdGE/DQoNCiMjIyMNCg0KIyAqKkxlYXJuaW5nIE9iamVjdGl2ZXMqKg0KKioqDQoNCkluIHRoaXMgY2FzZSBzdHVkeSwgd2Ugd2lsbCB3YWxrIHlvdSB0aHJvdWdoIGltcG9ydGluZyBkYXRhIGZyb20gQ1NWIGZpbGVzIGFuZCBwZXJmb3JtaW5nIG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcyB0byBwcmVkaWN0IG91ciBvdXRjb21lIHZhcmlhYmxlIG9mIGludGVyZXN0IChpbiB0aGlzIGNhc2UgYW5udWFsIGZpbmUgcGFydGljbGUgYWlyIHBvbGx1dGlvbiBlc3RpbWF0ZXMpLiANCg0KV2Ugd2lsbCBlc3BlY2lhbGx5IGZvY3VzIG9uIHVzaW5nIHBhY2thZ2VzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgW2B0aWR5dmVyc2VgXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSwgYW5kIG1vcmUgc3BlY2lmaWNhbGx5IHRoZSBbYHRpZHltb2RlbHNgXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdGlkeW1vZGVscy90aWR5bW9kZWxzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSBwYWNrYWdlL2Vjb3N5c3RlbSBwcmltYXJpbHkgZGV2ZWxvcGVkIGFuZCBtYWludGFpbmVkIGJ5IFtNYXggS3Vobl0oaHR0cHM6Ly9yZXNvdXJjZXMucnN0dWRpby5jb20vYXV0aG9ycy9tYXgta3Vobil7dGFyZ2V0PSJfYmxhbmsifSBhbmQgW0RhdmlzIFZhdWdoYW5dKGh0dHBzOi8vcmVzb3VyY2VzLnJzdHVkaW8uY29tL2F1dGhvcnMvZGF2aXMtdmF1Z2hhbil7dGFyZ2V0PSJfYmxhbmsifS4gDQpUaGlzIHBhY2thZ2UgbG9hZHMgbW9yZSBtb2RlbGluZyByZWxhdGVkIHBhY2thZ2VzIGxpa2UgYHJzYW1wbGVgLCBgcmVjaXBlc2AsIGBwYXJzbmlwYCwgYHlhcmRzdGlja2AsIGB3b3JrZmxvd3NgLCBhbmQgYHR1bmVgIHBhY2thZ2VzLiANCg0KVGhlIHRpZHl2ZXJzZSBpcyBhIGxpYnJhcnkgb2YgcGFja2FnZXMgY3JlYXRlZCBieSBSU3R1ZGlvLiANCldoaWxlIHNvbWUgc3R1ZGVudHMgbWF5IGJlIGZhbWlsaWFyIHdpdGggcHJldmlvdXMgUiBwcm9ncmFtbWluZyBwYWNrYWdlcywgdGhlc2UgcGFja2FnZXMgbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBlc3BlY2lhbGx5IGxlZ2libGUgYW5kIGludHVpdGl2ZS4NCg0KDQpgYGB7ciwgb3V0LndpZHRoID0gIjIwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0NCmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vdGlkeXZlcnNlLnRpZHl2ZXJzZS5vcmcvbG9nby5wbmciKQ0KYGBgDQoNClRoZSBza2lsbHMsIG1ldGhvZHMsIGFuZCBjb25jZXB0cyB0aGF0IHN0dWRlbnRzIHdpbGwgYmUgZmFtaWxpYXIgd2l0aCBieSB0aGUgZW5kIG9mIHRoaXMgY2FzZSBzdHVkeSBhcmU6DQoNCg0KPHU+KipEYXRhIFNjaWVuY2UgTGVhcm5pbmcgT2JqZWN0aXZlczoqKjwvdT4gDQogIA0KMS4gRmFtaWxpYXJpdHkgd2l0aCB0aGUgdGlkeW1vZGVscyBlY29zeXN0ZW0NCjIuIEFiaWxpdHkgdG8gZXZhbHVhdGUgY29ycmVsYXRpb24gYW1vbmcgcHJlZGljdG9yIHZhcmlhYmxlcyAoYGNvcnJwbG90YCBhbmQgYEdHYWxseWApDQozLiBBYmlsaXR5IHRvIGltcGxlbWVudCB0aWR5bW9kZWxzIHBhY2thZ2VzIHN1Y2ggYXMgYHJzYW1wbGVgIHRvIHNwbGl0IHRoZSBkYXRhIGludG8gdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0cyBhcyB3ZWxsIGFzIGNyb3NzIHZhbGlkYXRpb24gc2V0cy4NCjQuIEFiaWxpdHkgdG8gdXNlIHRoZSBgcmVjaXBlc2AsIGBwYXJzbmlwYCwgYW5kIGB3b3JrZmxvd3NgIHRvIHRyYWluIGFuZCB0ZXN0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgYW5kIHJhbmRvbSBmb3Jlc3QgbW9kZWwNCjUuIERlbW9uc3RyYXRlIGhvdyB0byB2aXN1YWxpemUgZ2VvLXNwYXRpYWwgZGF0YSB1c2luZyBgZ2dwbG90MmANCg0KPHU+KipTdGF0aXN0aWNhbCBMZWFybmluZyBPYmplY3RpdmVzOioqPC91PiAgDQogIA0KMS4gQmFzaWMgdW5kZXJzdGFuZGluZyB0aGUgdXRpbGl0eSBvZiBtYWNoaW5lIGxlYXJuaW5nIGZvciBwcmVkaWN0aW9uIGFuZCBjbGFzc2lmaWNhdGlvbg0KMi4gVW5kZXJzdGFuZGluZyBvZiB0aGUgbmVlZCBmb3IgdHJhaW5pbmcgYW5kIHRlc3Qgc2V0cw0KMy4gVW5kZXJzdGFuZGluZyBvZiB0aGUgdXRpbGl0eSBvZiBjcm9zcyB2YWxpZGF0aW9uDQo0LiBVbmRlcnN0YW5kaW5nIG9mIHJhbmRvbSBmb3Jlc3QNCjUuIEhvdyB0byBpbnRlcnByZXQgcm9vdCBtZWFuIHNxdWFyZWQgZXJyb3IgKHJtc2UpIHRvIGFzc2VzcyBwZXJmb3JtYW5jZSBmb3IgcHJlZGljdGlvbg0KDQoNCg0KYGBge3IsIG91dC53aWR0aCA9ICIxMDBweCIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0NCmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vcGJzLnR3aW1nLmNvbS9tZWRpYS9Ea0JGcFNzVzRBSXl5SU4ucG5nIikNCmBgYA0KDQoNCldlIHdpbGwgYmVnaW4gYnkgbG9hZGluZyB0aGUgcGFja2FnZXMgdGhhdCB3ZSB3aWxsIG5lZWQ6DQoNCmBgYHtyfQ0KbGlicmFyeShoZXJlKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHNraW1yKQ0KbGlicmFyeShzdW1tYXJ5dG9vbHMpDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KbGlicmFyeShHR2FsbHkpDQpsaWJyYXJ5KHRpZHltb2RlbHMpDQpsaWJyYXJ5KHdvcmtmbG93cykNCmxpYnJhcnkodmlwKQ0KbGlicmFyeSh0dW5lKQ0KbGlicmFyeShyYW5kb21Gb3Jlc3QpDQpsaWJyYXJ5KGRvUGFyYWxsZWwpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShsd2dlb20pDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShtYXBzKQ0KbGlicmFyeShybmF0dXJhbGVhcnRoKQ0KbGlicmFyeShyZ2VvcykNCmxpYnJhcnkocGF0Y2h3b3JrKQ0KYGBgDQoNCg0KIDx1PioqUGFja2FnZXMgdXNlZCBpbiB0aGlzIGNhc2Ugc3R1ZHk6KiogPC91Pg0KDQpQYWNrYWdlICAgfCBVc2UgaW4gdGhpcyBjYXNlIHN0dWR5ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQ0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGENCltyZWFkcl0oaHR0cHM6Ly9yZWFkci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gaW1wb3J0IENTViBmaWxlcw0KW2RwbHlyXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byB2aWV3L2FycmFuZ2UvZmlsdGVyL3NlbGVjdC9jb21wYXJlIHNwZWNpZmljIHN1YnNldHMgb2YgZGF0YSANCltza2ltcl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhDQpbc3VtbWFyeXRvb2xzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEgaW4gYSBkaWZmZXJlbnQgc3R5bGUNClttYWdyaXR0cl0oaHR0cHM6Ly9tYWdyaXR0ci50aWR5dmVyc2Uub3JnL2FydGljbGVzL21hZ3JpdHRyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHVzZSB0aGUgYCU8PiVgIHBpcHBpbmcgb3BlcmF0b3IgDQpbY29ycnBsb3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9jb3JycGxvdC92aWduZXR0ZXMvY29ycnBsb3QtaW50cm8uaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIG1ha2UgbGFyZ2UgY29ycmVsYXRpb24gcGxvdHMNCltHR2FsbHldKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9HR2FsbHkvR0dhbGx5LnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIG1ha2Ugc21hbGxlciBjb3JyZWxhdGlvbiBwbG90cyAgDQpbdGlkeW1vZGVsc10oaHR0cHM6Ly93d3cudGlkeW1vZGVscy5vcmcpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBsb2FkIGluIGEgc2V0IG9mIHBhY2thZ2VzIChicm9vbSwgZGlhbHMsIGluZmVyLCBwYXJzbmlwLCBwdXJyciwgcmVjaXBlcywgcnNhbXBsZSwgdGliYmxlLCB5YXJkc3RpY2spDQpbcnNhbXBsZV0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yc2FtcGxlL2FydGljbGVzL0Jhc2ljcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBzcGxpdCB0aGUgZGF0YSBpbnRvIHRlc3RpbmcgYW5kIHRyYWluaW5nIHNldHM7IHRvIHNwbGl0IHRoZSB0cmFpbmluZyBzZXQgZm9yIGNyb3NzLXZhbGlkYXRpb24gIA0KW3JlY2lwZXNdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy8pe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHByZS1wcm9jZXNzIGRhdGEgZm9yIG1vZGVsaW5nIGluIGEgdGlkeSBhbmQgcmVwcm9kdWNpYmxlIHdheSBhbmQgdG8gZXh0cmFjdCBwcmUtcHJvY2Vzc2VkIGRhdGEgKG1ham9yIGZ1bmN0aW9ucyBhcmUgYHJlY2lwZSgpYCwgYHByZXAoKWAgYW5kIHZhcmlvdXMgdHJhbnNmb3JtYXRpb24gYHN0ZXBfKigpYCBmdW5jdGlvbnMsIGFzIHdlbGwgYXMgYGJha2VgIHdoaWNoIGV4dHJhY3RzIHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSAodXNlZCB0byByZXF1aXJlIGBqdWljZSgpYCkgYW5kIGFwcGxpZXMgcmVjaXBlIHByZXByb2Nlc3Npbmcgc3RlcHMgdG8gdGVzdGluZyBkYXRhKS4gU2VlIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmVjaXBlcy9yZWNpcGVzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgZm9yIG1vcmUgaW5mby4NCltwYXJzbmlwXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3BhcnNuaXAvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCBhbiBpbnRlcmZhY2UgdG8gY3JlYXRlIG1vZGVscyAobWFqb3IgZnVuY3Rpb25zIGFyZSBgZml0KClgLCBgc2V0X2VuZ2luZSgpYCkNClt5YXJkc3RpY2tdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8veWFyZHN0aWNrLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIG1vZGVscw0KW2Jyb29tXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL2Jsb2cvMjAxOC8wNy9icm9vbS0wLTUtMC8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBnZXQgdGlkeSBvdXRwdXQgZm9yIG91ciBtb2RlbCBmaXQgYW5kIHBlcmZvcm1hbmNlDQpbZ2dwbG90Ml0oaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFrZSB2aXN1YWxpemF0aW9ucyB3aXRoIG11bHRpcGxlIGxheWVycw0KW2RpYWxzXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL2Jsb2cvMjAxOS8xMC9kaWFscy0wLTAtMy8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBzcGVjaWZ5IGh5cGVyLXBhcmFtZXRlciB0dW5pbmcNClt0dW5lXShodHRwczovL3R1bmUudGlkeW1vZGVscy5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gcGVyZm9ybSBjcm9zcyB2YWxpZGF0aW9uLCB0dW5lIGh5cGVyLXBhcmFtZXRlcnMsIGFuZCBnZXQgcGVyZm9ybWFuY2UgbWV0cmljcw0KW3dvcmtmbG93c10oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3dvcmtmbG93cy92ZXJzaW9ucy8wLjEuMSl7dGFyZ2V0PSJfYmxhbmsifXwgdG8gY3JlYXRlIG1vZGVsaW5nIHdvcmtmbG93IHRvIHN0cmVhbWxpbmUgdGhlIG1vZGVsaW5nIHByb2Nlc3MNClt2aXBdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy92aXAvdmlwLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGNyZWF0ZSB2YXJpYWJsZSBpbXBvcnRhbmNlIHBsb3RzDQpbcmFuZG9tRm9yZXN0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmFuZG9tRm9yZXN0L3JhbmRvbUZvcmVzdC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBwZXJmb3JtIHRoZSByYW5kb20gZm9yZXN0IGFuYWx5c2lzDQpbZG9QYXJhbGxlbF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2RvUGFyYWxsZWwvZG9QYXJhbGxlbC5wZGYpIHwgdG8gZml0IGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcyBpbiBwYXJhbGxlbCANCltzdHJpbmdyXShodHRwczovL3N0cmluZ3IudGlkeXZlcnNlLm9yZy9hcnRpY2xlcy9zdHJpbmdyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBtYW5pcHVsYXRlIHRoZSB0ZXh0IHRoZSBtYXAgZGF0YQ0KW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzZXBhcmF0ZSBkYXRhIHdpdGhpbiBhIGNvbHVtbiBpbnRvIG11bHRpcGxlIGNvbHVtbnMNCltybmF0dXJhbGVhcnRoXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcm5hdHVyYWxlYXJ0aC9SRUFETUUuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGdldCB0aGUgZ2VvbWV0cnkgZGF0YSBmb3IgdGhlIGVhcnRoIHRvIHBsb3QgdGhlIFVTDQpbbWFwc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hcHMvbWFwcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBnZXQgbWFwIGRhdGFiYXNlIGRhdGEgYWJvdXQgY291bnRpZXMgdG8gZHJhdyB0aGVtIG9uIG91ciBVUyBtYXANCltzZl0oaHR0cHM6Ly9yLXNwYXRpYWwuZ2l0aHViLmlvL3NmLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGNvbnZlcnQgdGhlIG1hcCBkYXRhIGludG8gYSBkYXRhIGZyYW1lDQpbbHdnZW9tXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbHdnZW9tL2x3Z2VvbS5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byB1c2UgdGhlIGBzZmAgZnVuY3Rpb24gdG8gY29udmVydCBtYXAgZ2VvZ3JhcGhpY2FsIGRhdGENCltyZ2Vvc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JnZW9zL3JnZW9zLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHVzZSBnZW9tZXRyeSBkYXRhDQpbcGF0Y2h3b3JrXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcGF0Y2h3b3JrL3BhdGNod29yay5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBhbGxvdyBwbG90cyB0byBiZSBjb21iaW5lZA0KX19fDQoNCg0KVGhlIGZpcnN0IHRpbWUgd2UgdXNlIGEgZnVuY3Rpb24sIHdlIHdpbGwgdXNlIHRoZSBgOjpgIHRvIGluZGljYXRlIHdoaWNoIHBhY2thZ2Ugd2UgYXJlIHVzaW5nLiANClVubGVzcyB3ZSBoYXZlIG92ZXJsYXBwaW5nIGZ1bmN0aW9uIG5hbWVzLCB0aGlzIGlzIG5vdCBuZWNlc3NhcnksIGJ1dCB3ZSB3aWxsIGluY2x1ZGUgaXQgaGVyZSB0byBiZSBpbmZvcm1hdGl2ZSBhYm91dCB3aGVyZSB0aGUgZnVuY3Rpb25zIHdlIHdpbGwgdXNlIGNvbWUgZnJvbS4NCg0KDQojICoqQ29udGV4dCoqDQoqKioNCg0KVGhlIFtTdGF0ZSBvZiBHbG9iYWwgQWlyXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gaXMgYSByZXBvcnQgcmVsZWFzZWQgZXZlcnkgeWVhciB0byBjb21tdW5pY2F0ZSB0aGUgaW1wYWN0IG9mIGFpciBwb2xsdXRpb24gb24gcHVibGljIGhlYWx0aC4gDQoNClRoZSBbU3RhdGUgb2YgR2xvYmFsIEFpciAyMDE5IHJlcG9ydF0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhXzIwMTlfcmVwb3J0LnBkZil7dGFyZ2V0PSJfYmxhbmsifQ0Kd2hpY2ggdXNlcyBkYXRhIGZyb20gMjAxNyBzdGF0ZWQgdGhhdDoNCg0KPiBBaXIgcG9sbHV0aW9uIGlzIHRoZSAqKmZpZnRoKiogbGVhZGluZyByaXNrIGZhY3RvciBmb3IgbW9ydGFsaXR5IHdvcmxkd2lkZS4gSXQgaXMgcmVzcG9uc2libGUgZm9yIG1vcmUNCmRlYXRocyB0aGFuIG1hbnkgYmV0dGVyLWtub3duIHJpc2sgZmFjdG9ycyBzdWNoIGFzIG1hbG51dHJpdGlvbiwgYWxjb2hvbCB1c2UsIGFuZCBwaHlzaWNhbCBpbmFjdGl2aXR5Lg0KRWFjaCB5ZWFyLCAqKm1vcmUqKiBwZW9wbGUgZGllIGZyb20gYWlyIHBvbGx1dGlvbuKAk3JlbGF0ZWQgZGlzZWFzZSB0aGFuIGZyb20gcm9hZCAqKnRyYWZmaWMgaW5qdXJpZXMqKiBvciAqKm1hbGFyaWEqKi4NCg0KPHAgYWxpZ249ImNlbnRlciI+DQo8aW1nIHdpZHRoPSI2MDAiIHNyYz0iaHR0cHM6Ly93d3cuaGVhbHRoZWZmZWN0cy5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9Tb0dBLUZpZ3VyZXMtMDEuanBnIj4NCjwvcD4NCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2FfMjAxOV9yZXBvcnQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9DQoNClRoZSByZXBvcnQgYWxzbyBzdGF0ZWQgdGhhdDoNCg0KPiBJbiAyMDE3LCBhaXIgcG9sbHV0aW9uIGlzIGVzdGltYXRlZCB0byBoYXZlIGNvbnRyaWJ1dGVkIHRvIGNsb3NlIHRvIDUgbWlsbGlvbg0KZGVhdGhzIGdsb2JhbGx5IOKAlCBuZWFybHkgKioxIGluIGV2ZXJ5IDEwIGRlYXRocyoqLg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIjIwMTdkZWF0aHMucG5nIikpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2FfMjAxOV9mYWN0X3NoZWV0LnBkZil7dGFyZ2V0PSJfYmxhbmsifQ0KDQpUaGUgW1N0YXRlIG9mIEdsb2JhbCBBaXIgMjAxOCByZXBvcnRdKGh0dHBzOi8vd3d3LnN0YXRlb2ZnbG9iYWxhaXIub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvc29nYS0yMDE4LXJlcG9ydC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gdXNpbmcgZGF0YSBmcm9tIDIwMTYgd2hpY2ggc2VwYXJhdGVkIGRpZmZlcmVudCB0eXBlcyBvZiBhaXIgcG9sbHV0aW9uLCBmb3VuZCB0aGF0ICoqcGFydGljdWxhdGUgcG9sbHV0aW9uIHdhcyBwYXJ0aWN1bGFybHkgYXNzb2NpYXRlZCB3aXRoIG1vcnRhbGl0eSoqLg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIjIwMTdtb3J0YWxpdHkucG5nIikpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2EtMjAxOC1yZXBvcnQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9DQoNClRoZSAyMDE5IHJlcG9ydCBzaG93cyB0aGF0IHRoZSBoaWdoZXN0IGxldmVscyBvZiBmaW5lIHBhcnRpY3VsYXRlIHBvbGx1dGlvbiBvY2N1cnMgaW4gQWZyaWNhIGFuZCBBc2lhIGFuZCB0aGF0Og0KDQo+IE1vcmUgdGhhbiAqKjkwJSoqIG9mIHBlb3BsZSB3b3JsZHdpZGUgbGl2ZSBpbiBhcmVhcyAqKmV4Y2VlZGluZyoqIHRoZSBXb3JsZCBIZWFsdGggT3JnYW5pemF0aW9uIChXSE8pICoqR3VpZGVsaW5lKiogZm9yIGhlYWx0aHkgYWlyLiBNb3JlIHRoYW4gaGFsZiBsaXZlIGluIGFyZWFzIHRoYXQgZG8gbm90IGV2ZW4gbWVldCBXSE8ncyBsZWFzdC1zdHJpbmdlbnQgYWlyIHF1YWxpdHkgdGFyZ2V0Lg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIlBNd29ybGQucG5nIikpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2FfMjAxOV9mYWN0X3NoZWV0LnBkZil7dGFyZ2V0PSJfYmxhbmsifQ0KDQpMb29raW5nIGF0IHRoZSBVUyBzcGVjaWZpY2FsbHksIGFpciBwb2xsdXRpb24gbGV2ZWxzIGFyZSBnZW5lcmFsbHkgaW1wcm92aW5nLCB3aXRoIGRlY2xpbmluZyBuYXRpb25hbCBhaXIgcG9sbHV0YW50IGNvbmNlbnRyYXRpb24gYXZlcmFnZXMgYXMgc2hvd24gZnJvbSB0aGUgMjAxOSBbKk91ciBOYXRpb24ncyBBaXIqXShodHRwczovL2dpc3B1Yi5lcGEuZ292L2Fpci90cmVuZHNyZXBvcnQvMjAxOS8jaG9tZSl7dGFyZ2V0PSJfYmxhbmsifSByZXBvcnQgZnJvbSB0aGUgVVMgRW52aXJvbm1lbnRhbCBQcm90ZWN0aW9uIEFnZW5jeSAoRVBBKTogDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiVVMucG5nIikpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2dpc3B1Yi5lcGEuZ292L2Fpci90cmVuZHNyZXBvcnQvMjAxOS9kb2N1bWVudGF0aW9uL0FpclRyZW5kc19GbHllci5wZGYpe3RhcmdldD0iX2JsYW5rIn0NCg0KSG93ZXZlciwgYWlyIHBvbGx1dGlvbiAqKmNvbnRpbnVlcyB0byBjb250cmlidXRlIHRvIGhlYWx0aCByaXNrIGZvciBBbWVyaWNhbnMqKiwgaW4gcGFydGljdWxhciBpbiAqKnJlZ2lvbnMgd2l0aCBoaWdoZXIgdGhhbiBuYXRpb25hbCBhdmVyYWdlIHJhdGVzKiogb2YgcG9sbHV0aW9uIHRoYXQgYWN0dWFsbHkgYXQgdGltZSBleGNlZWQgdGhlIFdITydzIHJlY29tbWVuZGVkIGxldmVsLiANClRodXMsIGl0IGlzIGltcG9ydGFudCB0byBvYnRhaW4gaGlnaCBzcGF0aWFsIGdyYW51bGFyaXR5IGluIGVzdGltYXRlcyBvZiBhaXIgcG9sbHV0aW9uIGluIG9yZGVyIHRvIGlkZW50aWZ5IGxvY2F0aW9ucyB3aGVyZSBwb3B1bGF0aW9ucyBhcmUgZXhwZXJpZW5jaW5nIGhhcm1mdWwgbGV2ZWxzIG9mIGV4cG9zdXJlLg0KDQpZb3UgY2FuIHNlZSB0aGF0IGN1cnJlbnQgYWlyIHF1YWxpdHkgY29uZGl0aW9ucyBhdCB0aGlzIFt3ZWJzaXRlXShodHRwczovL2FxaWNuLm9yZy9jaXR5L3VzYS8pe3RhcmdldD0iX2JsYW5rIn0gYW5kIHlvdSB3aWxsIG5vdGljZSB2YXJpYXRpb24gYWNyb3NzIGRpZmZlcmVudCBjaXRpZXMuDQoNCkZvciBleGFtcGxlLCBoZXJlIGFyZSB0aGUgY29uZGl0aW9ucyBpbiBUb3Bla2EgS2Fuc2FzIGF0IHRoZSB0aW1lIHRoaXMgY2FzZSBzdHVkeSB3YXMgY3JlYXRlZDoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJLYW5zYXMucG5nIikpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2FxaWNuLm9yZy9jaXR5L3VzYS8pe3RhcmdldD0iX2JsYW5rIn0NCg0KSXQgcmVwb3J0cyBwYXJ0aWN1bGF0ZSB2YWx1ZXMgdXNpbmcgd2hhdCBpcyBjYWxsZWQgdGhlIFtBaXIgUXVhbGl0eSBJbmRleF0oaHR0cHM6Ly93d3cuYWlybm93Lmdvdi9pbmRleC5jZm0/YWN0aW9uPWFxaWJhc2ljcy5hcWkpe3RhcmdldD0iX2JsYW5rIn0gKEFRSSkuDQpUaGlzIFtjYWxjdWxhdG9yXShodHRwczovL2Fpcm5vdy5nb3YvaW5kZXguY2ZtP2FjdGlvbj1haXJub3cuY2FsY3VsYXRvcil7dGFyZ2V0PSJfYmxhbmsifSBpbmRpY2F0ZXMgdGhhdCAxMTQgQVFJIGlzIGVxdWl2YWxlbnQgdG8gNDAuNyB1Zy9tXjNeIGFuZCBpcyBjb25zaWRlcmVkIHVuaGVhbHRoeSBmb3Igc2Vuc2l0aXZlIGluZGl2aWR1YWxzLg0KVGh1cywgc29tZSBhcmVhcyBleGNlZWQgdGhlIFdITyBhbm51YWwgZXhwb3N1cmUgZ3VpZGVsaW5lICgxMCB1Zy9tXjNeKSBhbmQgdGhpcyBtYXkgYWR2ZXJzZWx5IGFmZmVjdCB0aGUgaGVhbHRoIG9mIHBlb3BsZSBsaXZpbmcgaW4gdGhlc2UgbG9jYXRpb25zLg0KDQpBZHZlcnNlIGhlYWx0aCBlZmZlY3RzIGhhdmUgYmVlbiBhc3NvY2lhdGVkIHdpdGggcG9wdWxhdGlvbnMgZXhwZXJpZW5jaW5nIGhpZ2hlciBwb2xsdXRpb24gZXhwb3N1cmUgZGVzcGl0ZSB0aGUgbGV2ZWxzIGJlaW5nIGJlbG93IHN1Z2dlc3RlZCBndWlkZWxpbmVzLiANCkFsc28sIGl0IGFwcGVhcnMgdGhhdCB0aGUgY29tcG9zaXRpb24gb2YgdGhlIHBhcnRpY3VsYXRlIG1hdHRlciBhbmQgdGhlIGluZmx1ZW5jZSBvZiBvdGhlciBkZW1vZ3JhcGhpYyBmYWN0b3JzIG1heSBtYWtlIHNwZWNpZmljIHBvcHVsYXRpb25zIG1vcmUgYXQgcmlzayBmb3IgYWR2ZXJzZSBoZWFsdGggZWZmZWN0cyBkdWUgdG8gYWlyIHBvbGx1dGlvbi4gDQpGb3IgZXhhbXBsZSwgc2VlIHRoaXMgW2FydGljbGVdKGh0dHBzOi8vd3d3Lm5lam0ub3JnL2RvaS9mdWxsLzEwLjEwNTYvTkVKTW9hMTcwMjc0Nyl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9yZSBkZXRhaWxzLg0KDQpUaGUgbW9uaXRvciBkYXRhIHRoYXQgd2Ugd2lsbCB1c2UgaW4gdGhpcyBjYXNlIHN0dWR5IGNvbWUgZnJvbSBhIHN5c3RlbSBvZiBtb25pdG9ycyBpbiB3aGljaCByb3VnaGx5IDkwJSBhcmUgbG9jYXRlZCB3aXRoaW4gY2l0aWVzLiANCkhlbmNlLCB0aGVyZSBpcyBhbiAqKmVxdWl0eSBpc3N1ZSoqIGluIHRlcm1zIG9mIGNhcHR1cmluZyB0aGUgYWlyIHBvbGx1dGlvbiBsZXZlbHMgb2YgbW9yZSBydXJhbCBhcmVhcy4gDQpUbyBnZXQgYSBiZXR0ZXIgc2Vuc2Ugb2YgdGhlIHBvbGx1dGlvbiBleHBvc3VyZXMgZm9yIHRoZSBpbmRpdmlkdWFscyBsaXZpbmcgaW4gdGhlc2UgYXJlYXMsIG1ldGhvZHMgbGlrZSBtYWNoaW5lIGxlYXJuaW5nIGNhbiBiZSB1c2VmdWwgdG8gZXN0aW1hdGUgYWlyIHBvbGx1dGlvbiBsZXZlbHMgaW4gKiphcmVhcyB3aXRoIGxpdHRsZSB0byBubyBtb25pdG9yaW5nKiouIA0KU3BlY2lmaWNhbGx5LCB0aGVzZSBtZXRob2RzIGNhbiBiZSB1c2VkIHRvIGVzdGltYXRlIGFpciBwb2xsdXRpb24gaW4gdGhlc2UgbG93IG1vbml0b3JpbmcgYXJlYXMgc28gdGhhdCB3ZSBjYW4gbWFrZSBhIG1hcCBsaWtlIHRoaXMgd2hlcmUgd2UgaGF2ZSBhbm51YWwgZXN0aW1hdGVzIGZvciBhbGwgb2YgdGhlIGNvbnRpZ3VvdXMgVVM6DQoNCjxwIGFsaWduPSJjZW50ZXIiPg0KICA8aW1nIHdpZHRoPSI2MDAiIHNyYz0iaHR0cHM6Ly9hcmMtYW5nbGVyZmlzaC13YXNocG9zdC1wcm9kLXdhc2hwb3N0LnMzLmFtYXpvbmF3cy5jb20vcHVibGljL1NBV09FR0JYTVZHUTdBUzVQWjZVVU9YNkZZLnBuZyI+DQo8L3A+DQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS91cmw/c2E9aSZ1cmw9aHR0cHMlM0ElMkYlMkZ3d3cud2FzaGluZ3RvbnBvc3QuY29tJTJGYnVzaW5lc3MlMkYyMDE5JTJGMTAlMkYyMyUyRmFpci1wb2xsdXRpb24taXMtZ2V0dGluZy13b3JzZS1kYXRhLXNob3ctbW9yZS1wZW9wbGUtYXJlLWR5aW5nJTJGJnBzaWc9QU92VmF3M3YtWkRUQlBuTFAyTVl0S2YzVW5kaiZ1c3Q9MTU4NTc4NDQ3OTA2ODAwMCZzb3VyY2U9aW1hZ2VzJmNkPXZmZSZ2ZWQ9MENBSVFqUnhxRndvVENQQ3luOWZ4eGVnQ0ZRQUFBQUFkQUFBQUFCQWQpe3RhcmdldD0iX2JsYW5rIn0NCg0KVGhpcyBpcyB3aGF0IHdlIGFpbSB0byBhY2hpZXZlIGluIHRoaXMgY2FzZSBzdHVkeS4NCg0KIyAqKkxpbWl0YXRpb25zKioNCioqKg0KDQpUaGVyZSBhcmUgc29tZSBpbXBvcnRhbnQgY29uc2lkZXJhdGlvbnMgcmVnYXJkaW5nIHRoZSBkYXRhIGFuYWx5c2lzIGluIHRoaXMgY2FzZSBzdHVkeSB0byBrZWVwIGluIG1pbmQ6IA0KDQoxLiBUaGUgZGF0YSBkbyBub3QgaW5jbHVkZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY29tcG9zaXRpb24gb2YgcGFydGljdWxhdGUgbWF0dGVyLiBEaWZmZXJlbnQgdHlwZXMgb2YgcGFydGljdWxhdGVzIG1heSBiZSBtb3JlIGJlbmlnbiBvciBkZWxldGVyaW91cyBmb3IgaGVhbHRoIG91dGNvbWVzLg0KDQoyLiBPdXRkb29yIHBvbGx1dGlvbiBsZXZlbHMgYXJlIG5vdCBuZWNlc3NhcmlseSBhbiBpbmRpY2F0aW9uIG9mIGluZGl2aWR1YWwgZXhwb3N1cmVzLiBQZW9wbGUgc3BlbmQgZGlmZmVyaW5nIGFtb3VudHMgb2YgdGltZSBpbmRvb3JzIGFuZCBvdXRkb29ycyBhbmQgYXJlIGV4cG9zZWQgdG8gZGlmZmVyZW50IHBvbGx1dGlvbiBsZXZlbHMgaW5kb29ycy4gUmVzZWFyY2hlcnMgYXJlIG5vdyBkZXZlbG9waW5nIHBlcnNvbmFsIG1vbml0b3Jpbmcgc3lzdGVtcyB0byB0cmFjayBhaXIgcG9sbHV0aW9uIGxldmVscyBvbiB0aGUgcGVyc29uYWwgbGV2ZWwuDQoNCjMuIE91ciBhbmFseXNpcyB3aWxsIHVzZSBhbm51YWwgbWVhbiBlc3RpbWF0ZXMgb2YgcG9sbHV0aW9uIGxldmVscywgYnV0IHRoZXNlIGNhbiB2YXJ5IGdyZWF0bHkgYnkgc2Vhc29uLCBkYXkgYW5kIGV2ZW4gaG91ci4gVGhlcmUgYXJlIGRhdGEgc291cmNlcyB0aGF0IGhhdmUgZmluZXIgbGV2ZWxzIG9mIHRlbXBvcmFsIGRhdGEsIGhvd2V2ZXIgd2UgYXJlIGludGVyZXN0ZWQgaW4gbG9uZyB0ZXJtIGV4cG9zdXJlcywgYXMgdGhlc2UgYXBwZWFyIHRvIGJlIHRoZSBtb3N0IGluZmx1ZW50aWFsIGZvciBoZWFsdGggb3V0Y29tZXMsIHNvIHdlIGNob3NlIHRvIHVzZSBhbm51YWwgbGV2ZWwgZGF0YS4gDQoNCg0KIyAqKldoYXQgYXJlIHRoZSBkYXRhPyoqIHsjd2hhdGFyZXRoZWRhdGF9DQoqKioNCg0KV2hlbiB1c2luZyBtYWNoaW5lIGxlYXJuaW5nIGZvciBwcmVkaWN0aW9uLCB0aGVyZSBhcmUgdHdvIG1haW4gdHlwZXMgb2YgZGF0YSBvZiBpbnRlcmVzdDoNCg0KMS4gQSAqKmNvbnRpbnVvdXMqKiBvdXRjb21lIHZhcmlhYmxlIHRoYXQgd2Ugd2FudCB0byBwcmVkaWN0IA0KMi4gQSBzZXQgb2YgZmVhdHVyZShzKSAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykgdGhhdCB3ZSB1c2UgdG8gcHJlZGljdCB0aGUgb3V0Y29tZSB2YXJpYWJsZQ0KDQpUaGUgKipvdXRjb21lIHZhcmlhYmxlKiogaXMgd2hhdCB3ZSBhcmUgdHJ5aW5nIHRvICoqcHJlZGljdCoqLiANClRvIGJ1aWxkIChvciB0cmFpbikgb3VyIG1vZGVsLCB3ZSB1c2UgYm90aCB0aGUgb3V0Y29tZSBhbmQgZmVhdHVyZXMuDQpUaGUgZ29hbCBpcyB0byBpZGVudGlmeSBpbmZvcm1hdGl2ZSBmZWF0dXJlcyB0aGF0IGNhbiBleHBsYWluIGEgbGFyZ2UgYW1vdW50IG9mIHZhcmlhdGlvbiBpbiBvdXIgb3V0Y29tZSB2YXJpYWJsZS4gDQpVc2luZyB0aGlzIG1vZGVsLCB3ZSBjYW4gdGhlbiBwcmVkaWN0IHRoZSBvdXRjb21lIGZyb20gbmV3IG9ic2VydmF0aW9ucyB3aXRoIHRoZSBzYW1lIGZlYXR1cmVzIHdoZXJlIGhhdmUgbm90IG9ic2VydmVkIHRoZSBvdXRjb21lLiANCg0KQXMgYSBzaW1wbGUgZXhhbXBsZSwgaW1hZ2luZSB0aGF0IHdlIGhhdmUgZGF0YSBhYm91dCB0aGUgc2FsZXMgYW5kIGNoYXJhY3RlcmlzdGljcyBvZiBjYXJzIGZyb20gbGFzdCB5ZWFyIGFuZCB3ZSB3YW50IHRvIHByZWRpY3Qgd2hpY2ggY2FycyBtaWdodCBzZWxsIHdlbGwgdGhpcyB5ZWFyLiANCldlIGRvIG5vdCBoYXZlIHRoZSBzYWxlcyBkYXRhIHlldCBmb3IgdGhpcyB5ZWFyLCBidXQgd2UgZG8ga25vdyB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIG91ciBjYXJzIGZvciB0aGlzIHllYXIuIA0KV2UgY2FuIGJ1aWxkIGEgbW9kZWwgb2YgdGhlIGNoYXJhY3RlcmlzdGljcyB0aGF0IGV4cGxhaW5lZCBzYWxlcyBsYXN0IHllYXIgdG8gZXN0aW1hdGUgd2hhdCBjYXJzIG1pZ2h0IHNlbGwgd2VsbCB0aGlzIHllYXIuIA0KSW4gdGhpcyBjYXNlLCBvdXIgb3V0Y29tZSB2YXJpYWJsZSBpcyB0aGUgc2FsZXMgb2YgY2Fycywgd2hpbGUgdGhlIGRpZmZlcmVudCBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIGNhcnMgbWFrZSB1cCBvdXIgZmVhdHVyZXMuDQoNCiMjIyAqKlN0YXJ0IHdpdGggYSBxdWVzdGlvbioqDQoqKioNCg0KVGhpcyBpcyB0aGUgbW9zdCBjb21tb25seSBtaXNzZWQgc3RlcCB3aGVuIGRldmVsb3BpbmcgYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobS4gDQpNYWNoaW5lIGxlYXJuaW5nIGNhbiB2ZXJ5IGVhc2lseSBiZSB0dXJuZWQgaW50byBhbiBlbmdpbmVlcmluZyBwcm9ibGVtLiANCkp1c3QgZHVtcCB0aGUgb3V0Y29tZSBhbmQgdGhlIGZlYXR1cmVzIGludG8gYSBibGFjayBib3ggYWxnb3JpdGhtIGFuZCB2aW9sYSEgDQpCdXQgdGhpcyBraW5kIG9mIHRoaW5raW5nIGNhbiBsZWFkIHRvIG1ham9yIHByb2JsZW1zLiBJbiBnZW5lcmFsIGdvb2QgbWFjaGluZSBsZWFybmluZyBxdWVzdGlvbnM6DQoNCjEuIEhhdmUgYSBwbGF1c2libGUgZXhwbGFuYXRpb24gZm9yIHdoeSB0aGUgZmVhdHVyZXMgcHJlZGljdCB0aGUgb3V0Y29tZS4gDQoyLiBDb25zaWRlciBwb3RlbnRpYWwgdmFyaWF0aW9uIGluIGJvdGggdGhlIGZlYXR1cmVzIGFuZCB0aGUgb3V0Y29tZSBvdmVyIHRpbWUNCjMuIEFyZSBjb25zaXN0ZW50bHkgcmUtZXZhbHVhdGVkIG9uIGNyaXRlcmlhIDEgYW5kIDIgb3ZlciB0aW1lLiANCg0KSW4gdGhpcyBjYXNlIHN0dWR5LCB3ZSB3YW50IHRvICoqcHJlZGljdCoqIGFpciBwb2xsdXRpb24gbGV2ZWxzLiANClRvIGJ1aWxkIHRoaXMgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0sIG91ciAqKm91dGNvbWUgdmFyaWFibGUqKiBpcyBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciAoUE1+Mi41fikgY2FwdHVyZWQgZnJvbSBhaXIgcG9sbHV0aW9uIG1vbml0b3JzIGluIHRoZSBjb250aWd1b3VzIFVTIGZyb20gMjAwOC4gDQpPdXIgKipmZWF0dXJlcyoqIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKSBpbmNsdWRlIGRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5LCByb2FkIGRlbnNpdHksIHVyYmFuaXphdGlvbiBsZXZlbHMsIGFuZCBOQVNBIHNhdGVsbGl0ZSBkYXRhLiANCg0KQWxsIG9mIG91ciBkYXRhIHdhcyBwcmV2aW91c2x5IGNvbGxlY3RlZCBieSBhIFtyZXNlYXJjaGVyXShodHRwOi8vd3d3LmJpb3N0YXQuamhzcGguZWR1L35ycGVuZy8pIGF0IHRoZSBbSm9obnMgSG9wa2lucyBTY2hvb2wgb2YgUHVibGljIEhlYWx0aF0oaHR0cHM6Ly93d3cuamhzcGguZWR1Lykgd2hvIHN0dWRpZXMgYWlyIHBvbGx1dGlvbiBhbmQgY2xpbWF0ZSBjaGFuZ2UuIA0KDQoNCiMjIyAqKk91ciBvdXRjb21lIHZhcmlhYmxlKioNCioqKg0KDQpUaGUgbW9uaXRvciBkYXRhIHRoYXQgd2Ugd2lsbCBiZSB1c2luZyBjb21lcyBmcm9tICoqW2dyYXZpbWV0cmljIG1vbml0b3JzXShodHRwczovL3B1YmxpY2xhYi5vcmcvd2lraS9maWx0ZXItcG0pe3RhcmdldD0iX2JsYW5rIn0qKiAoc2VlIHBpY3R1cmUgYmVsb3cpIG9wZXJhdGVkIGJ5IHRoZSBVUyBbRW52aXJvbm1lbnRhbCBQcm90ZWN0aW9uIEFnZW5jeSAoRVBBKV0oaHR0cHM6Ly93d3cuZXBhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0uDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iMTAwcHgifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwibW9uaXRvci5wbmciKSkNCmBgYA0KDQojIyMjIyBbaW1hZ2UgY3VydGVzeSBvZiBbS2lyc3RlbiBLb2VobGVyXShodHRwczovL3d3dy5qaHNwaC5lZHUvZmFjdWx0eS9kaXJlY3RvcnkvcHJvZmlsZS8yOTI4L2tpcnN0ZW4ta29laGxlcildDQoNClRoZXNlIG1vbml0b3JzIHVzZSBhIGZpbHRyYXRpb24gc3lzdGVtIHRvIHNwZWNpZmljYWxseSBjYXB0dXJlIGZpbmUgcGFydGljdWxhdGUgbWF0dGVyLiANCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSIxNTBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJmaWx0ZXIucG5nIikpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3B1YmxpY2xhYi5vcmcvd2lraS9maWx0ZXItcG0pe3RhcmdldD0iX2JsYW5rIn0NCg0KVGhlIHdlaWdodCBvZiB0aGlzIHBhcnRpY3VsYXRlIG1hdHRlciBpcyBtYW51YWxseSBtZWFzdXJlZCBkYWlseSBvciB3ZWVrbHkuIA0KRm9yIHRoZSBFUEEgc3RhbmRhcmQgb3BlcmF0aW5nIHByb2NlZHVyZSBmb3IgUE0gZ3JhdmltZXRyaWMgYW5hbHlzaXMgaW4gMjAwOCwgd2UgcmVmZXIgdGhlIHJlYWRlciB0byBbaGVyZV0oaHR0cHM6Ly93d3czLmVwYS5nb3YvdHRuYW10aTEvZmlsZXMvYW1iaWVudC9wbTI1L3NwZWMvUlRJR3Jhdk1hc3NTT1BGSU5BTC5wZGYpe3RhcmdldD0iX2JsYW5rIn0uDQoNCjxkZXRhaWxzPjxzdW1tYXJ5PkZvciBtb3JlIG9uIEdyYXZpbWV0cmljIGFuYWx5c2lzLCB5b3UgY2FuIGV4cGFuZCBoZXJlIDwvc3VtbWFyeT4NCg0KR3JhdmltZXRyaWMgYW5hbHlzaXMgaXMgYWxzbyB1c2VkIGZvciBbZW1pc3Npb24gdGVzdGluZ10oaHR0cHM6Ly93d3cubXQuY29tL3VzL2VuL2hvbWUvYXBwbGljYXRpb25zL0xhYm9yYXRvcnlfd2VpZ2hpbmcvZW1pc3Npb25zLXRlc3RpbmctcGFydGljdWxhdGUtbWF0dGVyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0uIA0KVGhlIHNhbWUgaWRlYSBhcHBsaWVzOiBhIGZyZXNoIGZpbHRlciBpcyBhcHBsaWVkIGFuZCB0aGUgZGVzaXJlZCBhbW91bnQgb2YgdGltZSBwYXNzZXMsIHRoZW4gdGhlIGZpbHRlciBpcyByZW1vdmVkIGFuZCB3ZWlnaGVkLiANCg0KVGhlcmUgYXJlIFtvdGhlciBtb25pdG9yaW5nIHN5c3RlbXNdKGh0dHBzOi8vd3d3LnNlbnNpcmlvbi5jb20vZW4vYWJvdXQtdXMvbmV3c3Jvb20vc2Vuc2lyaW9uLXNwZWNpYWxpc3QtYXJ0aWNsZXMvcGFydGljdWxhdGUtbWF0dGVyLXNlbnNpbmctZm9yLWFpci1xdWFsaXR5LW1lYXN1cmVtZW50cy8pe3RhcmdldD0iX2JsYW5rIn0gdGhhdCBjYW4gcHJvdmlkZSBob3VybHkgbWVhc3VyZW1lbnRzLCBidXQgd2Ugd2lsbCBub3QgYmUgdXNpbmcgZGF0YSBmcm9tIHRoZXNlIG1vbml0b3JzIGluIG91ciBhbmFseXNpcy4gDQpHcmF2aW1ldHJpYyBhbmFseXNpcyBpcyBjb25zaWRlcmVkIHRvIGJlIGFtb25nIHRoZSBtb3N0IGFjY3VyYXRlIG1ldGhvZHMgZm9yIG1lYXN1cmluZyBwYXJ0aWN1bGF0ZSBtYXR0ZXIuDQoNCjwvZGV0YWlscz4NCg0KSW4gb3VyIGRhdGEgc2V0LCB0aGUgYHZhbHVlYCBjb2x1bW4gaW5kaWNhdGVzIHRoZSBQTX4yLjV+IG1vbml0b3IgYXZlcmFnZSBmb3IgMjAwOCBpbiBtYXNzIG9mIGZpbmUgcGFydGljbGVzL3ZvbHVtZSBvZiBhaXIgZm9yIDg3NiBncmF2aW1ldHJpYyBtb25pdG9ycy4gDQpUaGUgdW5pdHMgYXJlIG1pY3JvZ3JhbXMgb2YgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIgKFBNKSB0aGF0IGlzIGxlc3MgdGhhbiAyLjUgbWljcm9tZXRlcnMgaW4gZGlhbWV0ZXIgcGVyIGN1YmljIG1ldGVyIG9mIGFpciAtIG1hc3MgY29uY2VudHJhdGlvbiAodWcvbV4zXikuDQpSZWNhbGwgdGhlIFdITyBleHBvc3VyZSBndWlkZWxpbmUgaXMgPCAxMCB1Zy9tXjNeIG9uIGF2ZXJhZ2UgYW5udWFsbHkgZm9yIFBNfjIuNX4uDQoNCiMjIyAqKk91ciBmZWF0dXJlcyAocHJlZGljdG9yIHZhcmlhYmxlcykqKg0KKioqDQoNClRoZXJlIGFyZSA0OCBmZWF0dXJlcyB3aXRoIHZhbHVlcyBmb3IgZWFjaCBvZiB0aGUgODc2IG1vbml0b3JzIChvYnNlcnZhdGlvbnMpLiANClRoZSBkYXRhIGNvbWVzIGZyb20gdGhlIFVTIFtFbnZpcm9ubWVudGFsIFByb3RlY3Rpb24gQWdlbmN5IChFUEEpXShodHRwczovL3d3dy5lcGEuZ292Lyl7dGFyZ2V0PSJfYmxhbmsifSwgdGhlIFtOYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24gKE5BU0EpXShodHRwczovL3d3dy5uYXNhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0sIHRoZSBVUyBbQ2Vuc3VzXShodHRwczovL3d3dy5jZW5zdXMuZ292L2Fib3V0L3doYXQvY2Vuc3VzLWF0LWEtZ2xhbmNlLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0sIGFuZCB0aGUgW05hdGlvbmFsIENlbnRlciBmb3IgSGVhbHRoIFN0YXRpc3RpY3MgKE5DSFMpXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvYWJvdXQvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9Lg0KDQo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byBzZWUgYSB0YWJsZSBhYm91dCB0aGUgc2V0IG9mIGZlYXR1cmVzIDwvc3VtbWFyeT4NCg0KVmFyaWFibGUgICB8IERldGFpbHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0NCioqaWQqKiAgfCBNb25pdG9yIG51bWJlciAgPGJyPiAtLSB0aGUgY291bnR5IG51bWJlciBpcyBpbmRpY2F0ZWQgYmVmb3JlIHRoZSBkZWNpbWFsIDxicj4gLS0gdGhlIG1vbml0b3IgbnVtYmVyIGlzIGluZGljYXRlZCBhZnRlciB0aGUgZGVjaW1hbCA8YnI+ICAqKkV4YW1wbGUqKjogMTA3My4wMDIzICBpcyBKZWZmZXJzb24gY291bnR5ICgxMDczKSBhbmQgLjAwMjMgb25lIG9mIDggbW9uaXRvcnMgDQoqKmZpcHMqKiB8IEZlZGVyYWwgaW5mb3JtYXRpb24gcHJvY2Vzc2luZyBzdGFuZGFyZCBudW1iZXIgZm9yIHRoZSBjb3VudHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZCA8YnI+IC0tIDUgZGlnaXQgaWQgY29kZSBmb3IgY291bnRpZXMgKHplcm8gaXMgb2Z0ZW4gdGhlIGZpcnN0IHZhbHVlIGFuZCBzb21ldGltZXMgaXMgbm90IHNob3duKSA8YnI+IC0tIHRoZSBmaXJzdCAyIG51bWJlcnMgaW5kaWNhdGUgdGhlIHN0YXRlIDxicj4gLS0gdGhlIGxhc3QgdGhyZWUgbnVtYmVycyBpbmRpY2F0ZSB0aGUgY291bnR5IDxicj4gICoqRXhhbXBsZSoqOiBBbGFiYW1hJ3Mgc3RhdGUgY29kZSBpcyAwMSBiZWNhdXNlIGl0IGlzIGZpcnN0IGFscGhhYmV0aWNhbGx5IDxicj4gKG5vdGU6IEFsYXNrYSBhbmQgSGF3YWlpIGFyZSBub3QgaW5jbHVkZWQgYmVjYXVzZSB0aGV5IGFyZSBub3QgcGFydCBvZiB0aGUgY29udGlndW91cyBVUykgIA0KKipMYXQqKiB8IExhdGl0dWRlIG9mIHRoZSBtb25pdG9yIGluIGRlZ3JlZXMgIA0KKipMb24qKiB8IExvbmdpdHVkZSBvZiB0aGUgbW9uaXRvciBpbiBkZWdyZWVzICANCioqc3RhdGUqKiB8IFN0YXRlIHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQNCioqY291bnR5KiogfCBDb3VudHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZA0KKipjaXR5KiogfCBDaXR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQNCioqQ01BUSoqICB8IEVzdGltYXRlZCB2YWx1ZXMgb2YgYWlyIHBvbGx1dGlvbiBmcm9tIGEgY29tcHV0YXRpb25hbCBtb2RlbCBjYWxsZWQgWyoqQ29tbXVuaXR5IE11bHRpc2NhbGUgQWlyIFF1YWxpdHkgKENNQVEpKipdKGh0dHBzOi8vd3d3LmVwYS5nb3YvY21hcSl7dGFyZ2V0PSJfYmxhbmsifSA8YnI+IC0tICBBIG1vbml0b3Jpbmcgc3lzdGVtIHRoYXQgc2ltdWxhdGVzIHRoZSBwaHlzaWNzIG9mIHRoZSBhdG1vc3BoZXJlIHVzaW5nIGNoZW1pc3RyeSBhbmQgd2VhdGhlciBkYXRhIHRvIHByZWRpY3QgdGhlIGFpciBwb2xsdXRpb24gPGJyPiAtLSAqKipEb2VzIG5vdCB1c2UgYW55IG9mIHRoZSBQTX4yLjV+IGdyYXZpbWV0cmljIG1vbml0b3JpbmcgZGF0YS4qKiogKFRoZXJlIGlzIGEgdmVyc2lvbiB0aGF0IGRvZXMgdXNlIHRoZSBncmF2aW1ldHJpYyBtb25pdG9yaW5nIGRhdGEsIGJ1dCBub3QgdGhpcyBvbmUhKSA8YnI+IC0tIERhdGEgZnJvbSB0aGUgRVBBDQoqKnpjdGEqKiB8IFtaaXAgQ29kZSBUYWJ1bGF0aW9uIEFyZWFdKGh0dHBzOi8vd3d3Mi5jZW5zdXMuZ292L2dlby9wZGZzL2VkdWNhdGlvbi9icm9jaHVyZXMvWkNUQXMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSBQb3N0YWwgWmlwIGNvZGVzIGFyZSBjb252ZXJ0ZWQgaW50byAiZ2VuZXJhbGl6ZWQgYXJlYWwgcmVwcmVzZW50YXRpb25zIiB0aGF0IGFyZSBub24tb3ZlcmxhcHBpbmcgIDxicj4gLS0gRGF0YSBmcm9tIHRoZSAyMDEwIENlbnN1cyAgDQoqKnpjdGFfYXJlYSoqIHwgTGFuZCBhcmVhIG9mIHRoZSB6aXAgY29kZSBhcmVhIGluIG1ldGVycyBzcXVhcmVkICA8YnI+IC0tIERhdGEgZnJvbSB0aGUgMjAxMCBDZW5zdXMgIA0KKip6Y3RhX3BvcCoqIHwgUG9wdWxhdGlvbiBpbiB0aGUgemlwIGNvZGUgYXJlYSAgPGJyPiAtLSBEYXRhIGZyb20gdGhlIDIwMTAgQ2Vuc3VzICANCioqaW1wX2E1MDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgPGJyPiAtLSBJbXBlcnZpb3VzIHN1cmZhY2UgYXJlIHJvYWRzLCBjb25jcmV0ZSwgcGFya2luZyBsb3RzLCBidWlsZGluZ3MgPGJyPiAtLSBUaGlzIGlzIGEgbWVhc3VyZSBvZiBkZXZlbG9wbWVudCANCioqaW1wX2ExMDAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tICBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3INCioqaW1wX2E1MDAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tICBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgIA0KKippbXBfYTEwMDAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tICBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yICAgDQoqKmltcF9hMTUwMDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgIA0KKipjb3VudHlfYXJlYSoqIHwgTGFuZCBhcmVhIG9mIHRoZSBjb3VudHkgb2YgdGhlIG1vbml0b3IgaW4gbWV0ZXJzIHNxdWFyZWQgIA0KKipjb3VudHlfcG9wKiogfCBQb3B1bGF0aW9uIG9mIHRoZSBjb3VudHkgb2YgdGhlIG1vbml0b3IgIA0KKipMb2dfZGlzdF90b19wcmlzZWMqKiB8IExvZyAoTmF0dXJhbCBsb2cpIGRpc3RhbmNlIHRvIGEgcHJpbWFyeSBvciBzZWNvbmRhcnkgcm9hZCBmcm9tIHRoZSBtb25pdG9yIDxicj4gLS0gSGlnaHdheSBvciBtYWpvciByb2FkICANCioqbG9nX3ByaV9sZW5ndGhfNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIA0KKipsb2dfcHJpX2xlbmd0aF8xMDAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgPGJyPiAtLSBIaWdod2F5cyBvbmx5ICANCioqbG9nX3ByaV9sZW5ndGhfMTUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpIDxicj4gLS0gSGlnaHdheXMgb25seSAgDQoqKmxvZ19wcmlfbGVuZ3RoXzI1MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDI1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIA0KKipsb2dfcHJpc2VjX2xlbmd0aF81MDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgDQoqKmxvZ19wcmlzZWNfbGVuZ3RoXzEwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIA0KKipsb2dfcHJpc2VjX2xlbmd0aF81MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICANCioqbG9nX3ByaXNlY19sZW5ndGhfMTAwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICANCioqbG9nX3ByaXNlY19sZW5ndGhfMTUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICANCioqbG9nX3ByaXNlY19sZW5ndGhfMjUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAyNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAgICAgDQoqKmxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCoqIHwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxMDAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgDQoqKmxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xNTAwMCoqIHwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgIA0KKipsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMjUwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMjUwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICANCioqbG9nX25laV8yMDA4X3BtMTBfc3VtXzEwMDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgIA0KKipsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMTUwMDAqKnwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgICANCioqbG9nX25laV8yMDA4X3BtMTBfc3VtXzI1MDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDI1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgIA0KKipwb3BkZW5zX2NvdW50eSoqIHwgUG9wdWxhdGlvbiBkZW5zaXR5IChudW1iZXIgb2YgcGVvcGxlIHBlciBraWxvbWV0ZXIgc3F1YXJlZCBhcmVhIG9mIHRoZSBjb3VudHkpDQoqKnBvcGRlbnNfemN0YSoqIHwgUG9wdWxhdGlvbiBkZW5zaXR5IChudW1iZXIgb2YgcGVvcGxlIHBlciBraWxvbWV0ZXIgc3F1YXJlZCBhcmVhIG9mIHpjdGEpDQoqKm5vaHMqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciBpcyB0aGF0ICoqZG8gbm90IGhhdmUgYSBoaWdoIHNjaG9vbCBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzDQoqKnNvbWVocyoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzICoqc29tZSBoaWdoIHNjaG9vbCBlZHVjYXRpb24qKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzDQoqKmhzKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgY29tcGxldGluZyBhICoqaGlnaCBzY2hvb2wgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAgDQoqKnNvbWVjb2xsZWdlKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgY29tcGxldGluZyAqKnNvbWUgY29sbGVnZSBlZHVjYXRpb24qKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzIA0KKiphc3NvY2lhdGUqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBjb21wbGV0aW5nIGFuICoqYXNzb2NpYXRlIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgDQoqKmJhY2hlbG9yKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgYSAqKmJhY2hlbG9yJ3MgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyANCioqZ3JhZCoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGEgKipncmFkdWF0ZSBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzIA0KKipwb3YqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciBpcyB0aGF0IGxpdmVkIGluIFsqKnBvdmVydHkqKl0oaHR0cHM6Ly9hc3BlLmhocy5nb3YvMjAwOC1oaHMtcG92ZXJ0eS1ndWlkZWxpbmVzKSBpbiAyMDA4IC0gb3Igd291bGQgaXQgaGF2ZSBiZWVuIDIwMDcgZ3VpZGVsaW5lcz8/aHR0cHM6Ly9hc3BlLmhocy5nb3YvMjAwNy1oaHMtcG92ZXJ0eS1ndWlkZWxpbmVzIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgIA0KKipoc19vcmxlc3MqKiB8ICBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgYSAqKmhpZ2ggc2Nob29sIGRlZ3JlZSBvciBsZXNzKiogKHN1bSBvZiBub2hzLCBzb21laHMsIGFuZCBocykgIA0KKip1cmMyMDEzKiogfCBbMjAxMyBVcmJhbi1ydXJhbCBjbGFzc2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2RhdGEvc2VyaWVzL3NyXzAyL3NyMDJfMTY2LnBkZil7dGFyZ2V0PSJfYmxhbmsifSBvZiB0aGUgY291bnR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSA2IGNhdGVnb3J5IHZhcmlhYmxlIC0gMSBpcyB0b3RhbGx5IHVyYmFuIDYgaXMgY29tcGxldGVseSBydXJhbCA8YnI+ICAtLSBEYXRhIGZyb20gdGhlIFtOYXRpb25hbCBDZW50ZXIgZm9yIEhlYWx0aCBTdGF0aXN0aWNzXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICANCioqdXJjMjAwNioqIHwgWzIwMDYgVXJiYW4tcnVyYWwgY2xhc3NpZmljYXRpb25dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9kYXRhL3Nlcmllcy9zcl8wMi9zcjAyXzE1NC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gb2YgdGhlIGNvdW50eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkIDxicj4gLS0gNiBjYXRlZ29yeSB2YXJpYWJsZSAtIDEgaXMgdG90YWxseSB1cmJhbiA2IGlzIGNvbXBsZXRlbHkgcnVyYWwgPGJyPiAtLSBEYXRhIGZyb20gdGhlIFtOYXRpb25hbCBDZW50ZXIgZm9yIEhlYWx0aCBTdGF0aXN0aWNzXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICANCioqYW9kKiogfCBBZXJvc29sIE9wdGljYWwgRGVwdGggbWVhc3VyZW1lbnQgZnJvbSBhIE5BU0Egc2F0ZWxsaXRlIDxicj4gLS0gYmFzZWQgb24gdGhlIGRpZmZyYWN0aW9uIG9mIGEgbGFzZXIgPGJyPiAtLSB1c2VkIGFzIGEgcHJveHkgb2YgcGFydGljdWxhdGUgcG9sbHV0aW9uIDxicj4gLS0gdW5pdC1sZXNzIC0gaGlnaGVyIHZhbHVlIGluZGljYXRlcyBtb3JlIHBvbGx1dGlvbiA8YnI+IC0tIERhdGEgZnJvbSBOQVNBICANCg0KPC9kZXRhaWxzPg0KDQpNYW55IG9mIHRoZXNlIGZlYXR1cmVzIGhhdmUgdG8gZG8gd2l0aCB0aGUgY2lyY3VsYXIgYXJlYSBhcm91bmQgdGhlIG1vbml0b3IgY2FsbGVkIHRoZSAiYnVmZmVyIi4gVGhlc2UgYXJlIGlsbHVzdHJhdGVkIGluIHRoZSBmb2xsb3dpbmcgZmlndXJlOg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiODAwcHgiLH0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJyZWdyZXNzaW9uLnBuZyIpKQ0KYGBgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMTUyOTI5MDYpe3RhcmdldD0iX2JsYW5rIn0NCg0KDQoNCiMgKipEYXRhIEltcG9ydCoqDQoqKioNCg0KQWxsIG9mIG91ciBkYXRhIHdhcyBwcmV2aW91c2x5IGNvbGxlY3RlZCBieSBhIFtyZXNlYXJjaGVyXShodHRwOi8vd3d3LmJpb3N0YXQuamhzcGguZWR1L35ycGVuZy8pIGF0IHRoZSBbSm9obnMgSG9wa2lucyBTY2hvb2wgb2YgUHVibGljIEhlYWx0aF0oaHR0cHM6Ly93d3cuamhzcGguZWR1Lykgd2hvIHN0dWRpZXMgYWlyIHBvbGx1dGlvbiBhbmQgY2xpbWF0ZSBjaGFuZ2UuIA0KDQpXZSBoYXZlIG9uZSBDU1YgZmlsZSB0aGF0IGNvbnRhaW5zIGJvdGggb3VyIHNpbmdsZSAqKm91dGNvbWUgdmFyaWFibGUqKiBhbmQgYWxsIG9mIG91ciAqKmZlYXR1cmVzKiogKG9yIHByZWRpY3RvciB2YXJpYWJsZXMpLg0KDQpOZXh0LCB3ZSBpbXBvcnQgb3VyIGRhdGEgaW50byBSIG5vdyBzbyB0aGF0IHdlIGNhbiBleHBsb3JlIHRoZSBkYXRhIGZ1cnRoZXIuIA0KV2Ugd2lsbCBjYWxsIG91ciBkYXRhIG9iamVjdCBgcG1gIGZvciBwYXJ0aWN1bGF0ZSBtYXR0ZXIuIA0KV2UgaW1wb3J0IHRoZSBkYXRhIHVzaW5nIHRoZSBgcmVhZF9jc3YoKWAgZnVuY3Rpb24gZnJvbSB0aGUgYHJlYWRyYCBwYWNrYWdlLiANCmBgYHtyfQ0KcG0gPC0gcmVhZHI6OnJlYWRfY3N2KGhlcmUoImRvY3MiLCAicG0yNV9kYXRhLmNzdiIpKQ0KYGBgDQoNCg0KDQojICoqRGF0YSBFeHBsb3JhdGlvbiBhbmQgV3JhbmdsaW5nKioNCioqKg0KDQpUaGUgZmlyc3Qgc3RlcCBpbiBwZXJmb3JtaW5nIGFueSBkYXRhIGFuYWx5c2lzIGlzIHRvIGV4cGxvcmUgdGhlIGRhdGEuIA0KDQpGb3IgZXhhbXBsZSwgd2UgbWlnaHQgd2FudCB0byBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgdmFyaWFibGVzIGluY2x1ZGVkIGluIHRoZSBkYXRhLCBhcyB3ZSBtYXkgbGVhcm4gYWJvdXQgaW1wb3J0YW50IGRldGFpbHMgYWJvdXQgdGhlIGRhdGEgdGhhdCB3ZSBzaG91bGQga2VlcCBpbiBtaW5kIGFzIHdlIHRyeSB0byBwcmVkaWN0IG91ciBvdXRjb21lIHZhcmlhYmxlLg0KDQpGaXJzdCwgbGV0J3MganVzdCBnZXQgYSBnZW5lcmFsIHNlbnNlIG9mIG91ciBkYXRhLiANCldlIGNhbiBkbyB0aGF0IHVzaW5nIHRoZSBgZ2xpbXBzZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIChpdCBpcyBhbHNvIGluIHRoZSBgdGliYmxlYCBwYWNrYWdlKS4NCg0KV2Ugd2lsbCBhbHNvIHVzZSB0aGUgYCU+JWAgcGlwZSwgd2hpY2ggY2FuIGJlIHVzZWQgdG8gZGVmaW5lIHRoZSBpbnB1dCBmb3IgbGF0ZXIgc2VxdWVudGlhbCBzdGVwcy4gDQoNClRoaXMgd2lsbCBtYWtlIG1vcmUgc2Vuc2Ugd2hlbiB3ZSBoYXZlIG11bHRpcGxlIHNlcXVlbnRpYWwgc3RlcHMgdXNpbmcgdGhlIHNhbWUgZGF0YSBvYmplY3QuIA0KDQpUbyB1c2UgdGhlIHBpcGUgbm90YXRpb24gd2UgbmVlZCB0byBpbnN0YWxsIGFuZCBsb2FkIGBkcGx5cmAgYXMgd2VsbC4NCg0KRm9yIGV4YW1wbGUsIGhlcmUgd2Ugc3RhcnQgd2l0aCBgcG1gIGRhdGEgb2JqZWN0IGFuZCAicGlwZSIgdGhlIG9iamVjdCBpbnRvIGFzIGlucHV0IGludG8gdGhlIGBnbGltcHNlKClgIGZ1bmN0aW9uLiANClRoZSBvdXRwdXQgaXMgYW4gb3ZlcnZpZXcgb2Ygd2hhdCBpcyBpbiB0aGUgYHBtYCBvYmplY3Qgc3VjaCBhcyB0aGUgbnVtYmVyIG9mIHJvd3MgYW5kIGNvbHVtbnMsIGFsbCB0aGUgY29sdW1uIG5hbWVzLCB0aGUgZGF0YSB0eXBlcyBmb3IgZWFjaCBjb2x1bW4gYW5kIHRoZSBmaXJzdCB2aWV3IHZhbHVlcyBpbiBlYWNoIGNvbHVtbi4gDQpUaGUgb3V0cHV0IGJlbG93IGlzIHNjcm9sbGFibGUgc28geW91IGNhbiBzZWUgZXZlcnl0aGluZyBmcm9tIHRoZSBgZ2xpbXBzZSgpYCBmdW5jdGlvbi4gDQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCg0KYGBge3J9DQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhDQpwbSAlPiUNCiAgZHBseXI6OmdsaW1wc2UoKQ0KYGBgDQoNCiMjIyMNCg0KV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSA4NzYgbW9uaXRvcnMgKHJvd3MpIGFuZCB0aGF0IHdlIGhhdmUgNTAgdG90YWwgdmFyaWFibGVzIChjb2x1bW5zKSAtIG9uZSBvZiB3aGljaCBpcyB0aGUgb3V0Y29tZSB2YXJpYWJsZS4gSW4gdGhpcyBjYXNlLCB0aGUgb3V0Y29tZSB2YXJpYWJsZSBpcyBjYWxsZWQgYHZhbHVlYC4gDQoNCk5vdGljZSB0aGF0IHNvbWUgb2YgdGhlIHZhcmlhYmxlcyB0aGF0IHdlIHdvdWxkIHRoaW5rIG9mIGFzIGZhY3RvcnMgKG9yIGNhdGVnb3JpY2FsIGRhdGEpIGFyZSBjdXJyZW50bHkgb2YgY2xhc3MgY2hhcmFjdGVyIGFzIGluZGljYXRlZCBieSB0aGUgYDxjaHI+YCBqdXN0IHRvIHRoZSByaWdodCBvZiB0aGUgY29sdW1uIG5hbWVzL3ZhcmlhYmxlIG5hbWVzIGluIHRoZSBgZ2xpbXBzZSgpYCBvdXRwdXQuIFRoaXMgbWVhbnMgdGhhdCB0aGUgdmFyaWFibGUgdmFsdWVzIGFyZSBjaGFyYWN0ZXIgc3RyaW5ncywgc3VjaCBhcyB3b3JkcyBvciBwaHJhc2VzLiANCg0KVGhlIG90aGVyIHZhcmlhYmxlcyBhcmUgb2YgY2xhc3MgYDxkYmw+YCwgd2hpY2ggc3RhbmRzIGZvciBkb3VibGUgcHJlY2lzaW9uIHdoaWNoIGluZGljYXRlcyB0aGF0IHRoZXkgYXJlIG51bWVyaWMgYW5kIHRoYXQgdGhleSBoYXZlIGRlY2ltYWwgdmFsdWVzLiBJbiBjb250cmFzdCwgb25lIGNvdWxkIGhhdmUgaW50ZWdlciB2YWx1ZXMgd2hpY2ggd291bGQgbm90IGFsbG93IGZvciBkZWNpbWFsIG51bWJlcnMuIEhlcmUgaXMgYSBbbGlua10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRG91YmxlLXByZWNpc2lvbl9mbG9hdGluZy1wb2ludF9mb3JtYXQpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gZG91YmxlIHByZWNpc2lvbiBudW1lcmljIHZhbHVlcy4NCg0KQW5vdGhlciBjb21tb24gZGF0YSBjbGFzcyBpcyBmYWN0b3Igd2hpY2ggaXMgYWJicmV2aWF0ZWQgbGlrZSB0aGlzOiBgPGZjdD5gLiBBIGZhY3RvciBpcyBzb21ldGhpbmcgdGhhdCBoYXMgdW5pcXVlIGxldmVscyBidXQgdGhlcmUgaXMgbm8gYXBwcmVjaWFibGUgb3JkZXIgdG8gdGhlIGxldmVscy4gRm9yIGV4YW1wbGUgd2UgY2FuIGhhdmUgYSBudW1lcmljIHZhbHVlIHRoYXQgaXMganVzdCBhbiBpZCB0aGF0IHdlIHdhbnQgdG8gYmUgaW50ZXJwcmV0ZWQgYXMganVzdCBhIHVuaXF1ZSBsZXZlbCBhbmQgbm90IGFzIHRoZSBudW1iZXIgdGhhdCBpdCB3b3VsZCB0eXBpY2FsbHkgaW5kaWNhdGUuIFRoaXMgd291bGQgYmUgdXNlZnVsIGZvciBzZXZlcmFsIG9mIG91ciB2YXJpYWJsZXM6DQoNCjEuIHRoZSBtb25pdG9yIElEIChgaWRgKQ0KMi4gdGhlIEZlZGVyYWwgSW5mb3JtYXRpb24gUHJvY2Vzc2luZyBTdGFuZGFyZCBudW1iZXIgZm9yIHRoZSBjb3VudHkgd2hlcmUgdGhlIG1vbml0b3Igd2FzIGxvY2F0ZWQgKGBmaXBzYCkNCjMuIHRoZSB6aXAgY29kZSB0YWJ1bGF0aW9uIGFyZWEgKGB6Y3RhYCkNCg0KTm9uZSBvZiB0aGUgdmFsdWVzIGFjdHVhbGx5IGhhdmUgYW55IHJlYWwgbnVtZXJpYyBtZWFuaW5nLCBzbyB3ZSB3YW50IHRvIG1ha2Ugc3VyZSB0aGF0IFIgZG9lcyBub3QgaW50ZXJwcmV0IHRoZW0gYXMgaWYgdGhleSBkby4gDQoNClNvIGxldCdzIGNvbnZlcnQgdGhlc2UgdmFyaWFibGVzIGludG8gZmFjdG9ycy4gDQpXZSBjYW4gZG8gdGhpcyB1c2luZyB0aGUgYGFjcm9zcygpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIGFuZCB0aGUgYGFzLmZhY3RvcigpYCBiYXNlIGZ1bmN0aW9uLiANClRoZSBgYWNyb3NzKClgIGZ1bmN0aW9uIGhhcyB0d28gbWFpbiBhcmd1bWVudHM6IChpKSB0aGUgY29sdW1ucyB5b3Ugd2FudCB0byBvcGVyYXRlIG9uIGFuZCAoaWkpIHRoZSBmdW5jdGlvbiBvciBsaXN0IG9mIGZ1bmN0aW9ucyB0byBhcHBseSB0byBlYWNoIGNvbHVtbi4gDQoNCkluIHRoaXMgY2FzZSwgd2UgYXJlIGFsc28gdXNpbmcgdGhlIGBtYWdyaXR0cmAgYXNzaWdubWVudCBwaXBlIG9yIGRvdWJsZSBwaXBlIHRoYXQgbG9va3MgbGlrZSB0aGlzIGAlPD4lYCBvZiB0aGUgYG1hZ3JpdHRyYCBwYWNrYWdlLiANClRoaXMgYWxsb3dzIHVzIHVzZSB0aGUgYHBtYCBkYXRhIGFzIGlucHV0LCBidXQgYWxzbyByZWFzc2lnbnMgdGhlIG91dHB1dCB0byB0aGUgc2FtZSBkYXRhIG9iamVjdCBuYW1lLg0KDQojIyMjIHsuc2Nyb2xsYWJsZSB9DQoNCmBgYHtyfQ0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQ0KcG0gJTw+JQ0KICBtdXRhdGUoYWNyb3NzKGMoaWQsIGZpcHMsIHpjdGEpLCBhcy5mYWN0b3IpKSANCg0KZ2xpbXBzZShwbSkNCmBgYA0KDQojIyMjDQoNCkdyZWF0ISBOb3cgd2UgY2FuIHNlZSB0aGF0IHRoZXNlIHZhcmlhYmxlcyBhcmUgbm93IGZhY3RvcnMgYXMgaW5kaWNhdGVkIGJ5IGA8ZmN0PmAgYWZ0ZXIgdGhlIHZhcmlhYmxlIG5hbWUuDQoNCg0KDQojIyAqKmBza2ltYCBwYWNrYWdlKioNCioqKg0KDQpUaGUgYHNraW0oKWAgZnVuY3Rpb24gb2YgdGhlIGBza2ltcmAgcGFja2FnZSBpcyBhbHNvIHJlYWxseSBoZWxwZnVsIGZvciBnZXR0aW5nIGEgZ2VuZXJhbCBzZW5zZSBvZiB5b3VyIGRhdGEuDQpCeSBkZXNpZ24sIGl0IHByb3ZpZGVzIHN1bW1hcnkgc3RhdGlzdGljcyBhYm91dCB2YXJpYWJsZXMgaW4gdGhlIGRhdGEgc2V0LiANCg0KDQojIyMjIHsuc2Nyb2xsYWJsZSB9DQoNCmBgYHtyfQ0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQ0Kc2tpbXI6OnNraW0ocG0pDQpgYGANCg0KIyMjIw0KDQpOb3RpY2UgaG93IHRoZXJlIGlzIGEgY29sdW1uIGNhbGxlZCBgbl9taXNzaW5nYCBhYm91dCB0aGUgbnVtYmVyIG9mIHZhbHVlcyB0aGF0IGFyZSBtaXNzaW5nLiANCg0KVGhpcyBpcyBhbHNvIGluZGljYXRlZCBieSB0aGUgYGNvbXBsZXRlX3JhdGVgIHZhcmlhYmxlIChvciBtaXNzaW5nL251bWJlciBvZiBvYnNlcnZhdGlvbnMpLiANCg0KSW4gb3VyIGRhdGEgc2V0LCBpdCBsb29rcyBsaWtlIG91ciBkYXRhIGRvIG5vdCBjb250YWluIGFueSBtaXNzaW5nIGRhdGEuIA0KDQpBbHNvIG5vdGljZSBob3cgdGhlIGZ1bmN0aW9uIHByb3ZpZGVzIHNlcGFyYXRlIHRhYmxlcyBvZiBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIGVhY2ggZGF0YSB0eXBlOiBjaGFyYWN0ZXIsIGZhY3RvciBhbmQgbnVtZXJpYy4gDQoNCk5leHQsIHRoZSBgbl91bmlxdWVgIGNvbHVtbiBzaG93cyB1cyB0aGUgbnVtYmVyIG9mIHVuaXF1ZSB2YWx1ZXMgZm9yIGVhY2ggb2Ygb3VyIGNvbHVtbnMuIA0KV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSA0OSBzdGF0ZXMgcmVwcmVzZW50ZWQgaW4gdGhlIGRhdGEuDQoNCldlIGNhbiBzZWUgdGhhdCBmb3IgbWFueSB2YXJpYWJsZXMgdGhlcmUgYXJlIG1hbnkgbG93IHZhbHVlcyBhcyB0aGUgZGlzdHJpYnV0aW9uIHNob3dzIHR3byBwZWFrcywgb25lIG5lYXIgemVybyBhbmQgYW5vdGhlciB3aXRoIGEgaGlnaGVyIHZhbHVlLiANCg0KVGhpcyBpcyB0cnVlIGZvciB0aGUgYGltcGAgdmFyaWFibGVzIChtZWFzdXJlcyBvZiBkZXZlbG9wbWVudCksIHRoZSBgbmVpYCB2YXJpYWJsZXMgKG1lYXN1cmVzIG9mIGVtaXNzaW9uIHNvdXJjZXMpIGFuZCB0aGUgcm9hZCBkZW5zaXR5IHZhcmlhYmxlcy4gDQoNCldlIGNhbiBhbHNvIHNlZSB0aGF0IHRoZSByYW5nZSBvZiBzb21lIG9mIHRoZSB2YXJpYWJsZXMgaXMgdmVyeSBsYXJnZSwgaW4gcGFydGljdWxhciB0aGUgYXJlYSBhbmQgcG9wdWxhdGlvbiByZWxhdGVkIHZhcmlhYmxlcy4NCg0KDQpMZXQncyB0YWtlIGEgbG9vayB0byBzZWUgd2hpY2ggc3RhdGVzIGFyZSBpbmNsdWRlZCB1c2luZyB0aGUgYGRpc3RpbmN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2U6DQoNCmBgYHtyLCBldmFsID0gRkFMU0V9IA0KcG0gJT4lIA0KICBkcGx5cjo6ZGlzdGluY3Qoc3RhdGUpIA0KYGBgDQoNCg0KU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dDoNCg0KIyMjIyB7LnNjcm9sbGFibGUgfQ0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCENCnBtICU+JSANCiAgZGlzdGluY3Qoc3RhdGUpICU+JQ0KIyB0aGlzIGFsbG93cyB1cyB0byBzaG93IHRoZSBmdWxsIG91dHB1dCBpbiB0aGUgcmVuZGVyZWQgcm1hcmtkb3duDQogcHJpbnQobiA9IDFlMykNCmBgYA0KIyMjIw0KDQpJdCBsb29rcyBsaWtlICJEaXN0cmljdCBvZiBDb2x1bWJpYSIgaXMgYmVpbmcgaW5jbHVkZWQgYXMgYSBzdGF0ZS4gDQpXZSBjYW4gc2VlIHRoYXQgQWxhc2thIGFuZCBIYXdhaWkgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgZGF0YS4NCg0KTGV0J3MgYWxzbyB0YWtlIGEgbG9vayB0byBzZWUgaG93IG1hbnkgbW9uaXRvcnMgdGhlcmUgYXJlIGluIGEgZmV3IGNpdGllcy4gV2UgY2FuIHVzZSB0aGUgYGZpbHRlcigpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIHRvIGRvIHNvLiBGb3IgZXhhbXBsZSwgbGV0J3MgbG9vayBhdCBBbGJ1cXVlcnF1ZSwgTmV3IE1leGljby4gDQoNCmBgYHtyfQ0KcG0gJT4lIGRwbHlyOjpmaWx0ZXIoY2l0eSA9PSAiQWxidXF1ZXJxdWUiKQ0KDQpgYGANCg0KV2UgY2FuIHNlZSB0aGF0IHRoZXJlIHdlcmUgb25seSB0d28gbW9uaXRvcnMgaW4gdGhlIGNpdHkgb2YgQWxidXF1ZXJxdWUgaW4gMjAwNi4gTGV0J3MgY29tcGFyZSB0aGlzIHdpdGggQmFsdGltb3JlLg0KDQpgYGB7cn0NCnBtICU+JSBkcGx5cjo6ZmlsdGVyKGNpdHkgPT0gIkJhbHRpbW9yZSIpDQoNCmBgYA0KDQpUaGVyZSB3ZXJlIGluIGNvbnRyYXN0IGZpdmUgbW9uaXRvcnMgZm9yIHRoZSBjaXR5IG9mIEJhbHRpbW9yZSwgZGVzcGl0ZSB0aGUgZmFjdCB0aGF0IGlmIHdlIHRha2UgYSBsb29rIGF0IHRoZSBsYW5kIGFyZWEgYW5kIHBvcHVsYXRpb24gb2YgdGhlIGNvdW50aWVzIGZvciBCYWx0aW1vcmUgQ2l0eSBhbmQgQWxidXF1ZXJxdWUsIHdlIGNhbiBzZWUgdGhhdCB0aGV5IGhhZCB2ZXJ5IHNpbWlsYXIgbGFuZCBhcmVhIGFuZCBwb3B1bGF0aW9ucy4NCg0KYGBge3J9DQpwbSAlPiUgDQogIGRwbHlyOjpmaWx0ZXIoY2l0eSA9PSAiQmFsdGltb3JlIikgJT4lIA0KICBzZWxlY3QoY291bnR5X2FyZWE6Y291bnR5X3BvcCkNCnBtICU+JSANCiAgZHBseXI6OmZpbHRlcihjaXR5ID09ICJBbGJ1cXVlcnF1ZSIpICU+JQ0KICBzZWxlY3QoY291bnR5X2FyZWE6Y291bnR5X3BvcCkNCg0KYGBgDQoNCkluIGZhY3QsIHRoZSBjb3VudHkgY29udGFpbmluZyBBbGJ1ZXJxdWUgaGFkIGEgbGFyZ2VyIHBvcHVsYXRpb24uIFRodXMgdGhlIG1lYXN1cmVtZW50cyBmb3IgQWxidXF1ZXJxdWUgd2VyZSBub3QgYXMgdGhvcm91Z2ggYXMgdGhleSB3ZXJlIGZvciBCYWx0aW1vcmUuDQoNClRoaXMgbWF5IGJlIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZSBtb25pdG9yIHZhbHVlcyB3ZXJlIGxvd2VyIGluIEFsYnVxdWVycXVlLiBJdCBpcyBpbnRlcmVzdGluZyB0byBub3RlIGhlcmUgdGhhdCB0aGUgQ01BUSB2YWx1ZXMgYXJlIHF1aXRlIHNpbWlsYXIgZm9yIGJvdGggY2l0aWVzLg0KDQoNCiMjICoqRXZhbHVhdGUgY29ycmVsYXRpb24qKg0KKioqDQoNCkluIHByZWRpY3Rpb24gYW5hbHlzZXMsIGl0IGlzIGFsc28gdXNlZnVsIHRvIGV2YWx1YXRlIGlmIGFueSBvZiB0aGUgdmFyaWFibGVzIGFyZSBjb3JyZWxhdGVkLiBXaHkgc2hvdWxkIHdlIGNhcmUgYWJvdXQgdGhpcz8NCg0KSWYgd2UgYXJlIHVzaW5nIGEgbGluZWFyIHJlZ3Jlc3Npb24gdG8gbW9kZWwgb3VyIGRhdGEsIHRoZW4gd2UgbWlnaHQgcnVuIGludG8gYSBwcm9ibGVtIGNhbGxlZCBtdWx0aWNvbGxpbmVhcml0eSB3aGljaCBjYW4gbGVhZCB1cyB0byBtaXNpbnRlcnByZXQgd2hhdCBpcyByZWFsbHkgcHJlZGljdGl2ZSBvZiBvdXIgb3V0Y29tZSB2YXJpYWJsZS4gVGhpcyBwaGVub21lbm9uIG9jY3VycyB3aGVuIHRoZSBwcmVkaWN0b3IgdmFyaWFibGVzIGFjdHVhbGx5IHByZWRpY3Qgb25lIGFub3RoZXIuIFNlZSBbdGhpcyBjYXNlIHN0dWR5XShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vb2NzLWJwLVJUQy1hbmFseXNpcy8pIGZvciBhIGRlZXBlciBleHBsYW5hdGlvbiBhYm91dCB0aGlzLiANCg0KQW5vdGhlciByZWFzb24gd2Ugc2hvdWxkIGxvb2sgb3V0IGZvciBjb3JyZWxhdGlvbiBpcyB0aGF0IHdlIGRvbid0IHdhbnQgdG8gaW5jbHVkZSByZWR1bmRhbnQgdmFyaWFibGVzLiBUaGlzIGNhbiBhZGQgdW5uZWNlc3Nhcnkgbm9pc2UgdG8gb3VyIGFsZ29yaXRobSBjYXVzaW5nIGEgcmVkdWN0aW9uIGluIHByZWRpY3Rpb24gYWNjdXJhY3kgYW5kIGl0IGNhbiBjYXVzZSBvdXIgYWxnb3JpdGhtIHRvIGJlIHVubmVjZXNzYXJpbHkgc2xvd2VyLiBGaW5hbGx5LCBpdCBjYW4gYWxzbyBtYWtlIGl0IGRpZmZpY3VsdCB0byBpbnRlcnByZXQgd2hhdCB2YXJpYWJsZXMgYXJlIGFjdHVhbGx5IHByZWRpY3RpdmUuDQoNCkludHVpdGl2ZWx5IHdlIGNhbiBleHBlY3Qgc29tZSBvZiBvdXIgdmFyaWFibGVzIHRvIGJlIGNvcnJlbGF0ZWQuDQoNCkxldCdzIGZpcnN0IHRha2UgYSBsb29rIGF0IGFsbCBvZiBvdXIgbnVtZXJpYyB2YXJpYWJsZXMgd2l0aCB0aGVgY29ycnBsb3RgIHBhY2thZ2U6DQpUaGUgYGNvcnJwbG90YCBwYWNrYWdlIGlzIGFub3RoZXIgb3B0aW9uIHRvIGxvb2sgYXQgY29ycmVsYXRpb24gYW1vbmcgcG9zc2libGUgcHJlZGljdG9ycywgYW5kIHBhcnRpY3VsYXJseSB1c2VmdWwgaWYgd2UgaGF2ZSBtYW55IHByZWRpY3RvcnMuIA0KDQpGaXJzdCwgd2UgY2FsY3VsYXRlIHRoZSBQZWFyc29uIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyBiZXR3ZWVuIGFsbCBmZWF0dXJlcyBwYWlyd2lzZSB1c2luZyB0aGUgYGNvcigpYCBmdW5jdGlvbiBvZiB0aGUgYHN0YXRzYCBwYWNrYWdlICh3aGljaCBpcyBsb2FkZWQgYXV0b21hdGljYWxseSkuIFRoZW4gd2UgdXNlIHRoZSBgY29ycnBsb3Q6OmNvcnJwbG90KClgIGZ1bmN0aW9uLiANCg0KYGBge3J9DQpQTV9jb3IgPC0gY29yKHBtICU+JSBkcGx5cjo6c2VsZWN0X2lmKGlzLm51bWVyaWMpKQ0KY29ycnBsb3Q6OmNvcnJwbG90KFBNX2NvciwgdGwuY2V4ID0gMC41KQ0KYGBgDQpUaGUgYHRsLmNleCA9IDAuNWAgYXJndW1lbnQgY29udHJvbHMgdGhlIHNpemUgb2YgdGhlIHRleHQgbGFiZWwuIA0KDQpXZSBjYW4gYWxzbyBwbG90IHRoZSBhYnNvbHV0ZSB2YWx1ZSBvZiB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgdXNpbmcgdGhlIGBhYnMoKWAgZnVuY3Rpb24gZnJvbSBiYXNlIFIgYW5kIGNoYW5nZSB0aGUgb3JkZXIgb2YgdGhlIGNvbHVtbnMuICANCmBgYHtyfQ0KY29ycnBsb3QoYWJzKFBNX2NvciksIG9yZGVyID0gImhjbHVzdCIsIHRsLmNleCA9IDAuNSwgY2wubGltID0gYygwLCAxKSkNCg0KYGBgDQoNClRoZXJlIGFyZSBzZXZlcmFsIG9wdGlvbnMgZm9yIG9yZGVyaW5nIHRoZSB2YXJpYWJsZXMuIFNlZSBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2NvcnJwbG90L3ZpZ25ldHRlcy9jb3JycGxvdC1pbnRyby5odG1sKSBmb3IgbW9yZSBvcHRpb25zLiBIZXJlIHdlIHdpbGwgdXNlIHRoZSAiaGNsdXN0IiBvcHRpb24gZm9yIG9yZGVyaW5nIGJ5IFtoaWVyYXJjaGljYWwgY2x1c3RlcmluZ10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSGllcmFyY2hpY2FsX2NsdXN0ZXJpbmcpIC0gd2hpY2ggd2lsbCBvcmRlciB0aGUgdmFyaWFibGVzIGJ5IGhvdyBzaW1pbGFyIHRoZXkgYXJlIHRvIG9uZSBhbm90aGVyLg0KDQpUaGUgYGNsLmxpbSA9IGMoMCwgMSlgIGFyZ3VtZW50IGxpbWl0cyB0aGUgY29sb3IgbGFiZWwgdG8gYmUgYmV0d2VlbiAwIGFuZCAxLiANCg0KDQpXZSBjYW4gc2VlIHRoYXQgdGhlIGRldmVsb3BtZW50IHZhcmlhYmxlcyAoYGltcGApIHZhcmlhYmxlcyBhcmUgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIgYXMgd2UgbWlnaHQgZXhwZWN0LiANCldlIGFsc28gc2VlIHRoYXQgdGhlIHJvYWQgZGVuc2l0eSB2YXJpYWJsZXMgc2VlbSB0byBiZSBjb3JyZWxhdGVkIHdpdGggZWFjaCBvdGhlciwgYW5kIHRoZSBlbWlzc2lvbiB2YXJpYWJsZXMgc2VlbSB0byBiZSBjb3JyZWxhdGVkIHdpdGggZWFjaCBvdGhlci4gDQoNCg0KQWxzbyBub3RpY2UgdGhhdCBub25lIG9mIHRoZSBwcmVkaWN0b3JzIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIG91ciBvdXRjb21lIHZhcmlhYmxlIChgdmFsdWVgKS4NCg0KV2UgY2FuIHRha2UgYWxzbyB0YWtlIGEgY2xvc2VyIGxvb2sgIHVzaW5nIHRoZSBgZ2djb3JyKClgIGZ1bmN0aW9uIGFuZCB0aGUgYGdncGFpcnMoKWAgZnVuY3Rpb24gb2YgdGhlIGBHR2FsbHlgIHBhY2thZ2UuIA0KDQpUbyBzZWxlY3Qgb3VyIHZhcmlhYmxlcyBvZiBpbnRlcmVzdCB3ZSBjYW4gdXNlIHRoZSBgc2VsZWN0KClgIGZ1bmN0aW9uIHdpdGggdGhlIGBjb250YWlucygpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlLiANCg0KRmlyc3QgbGV0J3MgbG9vayBhdCB0aGUgYGltcGAvZGV2ZWxvcG1lbnQgdmFyaWFibGVzLiANCldlIGNhbiBjaGFuZ2UgdGhlIGRlZmF1bHQgY29sb3IgcGFsZXR0ZSAoYHBhbGV0dGUgPSAiUmRCdSJgKSBhbmQgYWRkIG9uIA0KY29ycmVsYXRpb24gY29lZmZpY2llbnRzIHRvIHRoZSBwbG90IChgbGFiZWwgPSBUUlVFYCkuDQoNCmBgYHtyLCBvdXQud2lkdGggPSAiNDAwcHgifQ0Kc2VsZWN0KHBtLCBjb250YWlucygiaW1wIikpICU+JQ0KICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgbGFiZWwgPSBUUlVFKQ0KDQpzZWxlY3QocG0sIGNvbnRhaW5zKCJpbXAiKSkgJT4lDQogIGdncGFpcnMoKQ0KYGBgDQoNCg0KDQpJbmRlZWQsIHdlIGNhbiBzZWUgdGhhdCBgaW1wX2ExMDAwYCBhbmQgYGltcF9hNTAwYCBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQsIGFzIHdlbGwgYXMgYGltcF9hMTAwMDBgLCBgaW1wX2ExNTAwMGAuDQoNCk5leHQsIGxldCdzIHRha2UgYSBsb29rIGF0IHRoZSByb2FkIGRlbnNpdHkgZGF0YToNCg0KYGBge3IsIGZpZy53ZWlnaHQ9MTJ9DQpzZWxlY3QocG0sIGNvbnRhaW5zKCJwcmkiKSkgJT4lDQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCBoanVzdCA9IC44NSwgc2l6ZSA9IDMsDQogICAgICAgbGF5b3V0LmV4cD0yLCBsYWJlbCA9IFRSVUUpDQpgYGANCg0KV2UgY2FuIHNlZSB0aGF0IG1hbnkgb2YgdGhlIHJvYWQgZGVuc2l0eSB2YXJpYWJsZXMgYXJlIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggb25lIGFub3RoZXIsIHdoaWxlIG90aGVycyBhcmUgbGVzcyBzby4NCg0KRmluYWxseSBsZXQncyBsb29rIGF0IHRoZSBlbWlzc2lvbiB2YXJpYWJsZXMuDQoNCmBgYHtyfQ0Kc2VsZWN0KHBtLCBjb250YWlucygibmVpIikpICU+JQ0KICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgaGp1c3QgPSAuODUsIHNpemUgPSAzLA0KICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQ0KDQpzZWxlY3QocG0sIGNvbnRhaW5zKCJuZWkiKSkgJT4lDQogIGdncGFpcnMoKQ0KYGBgDQoNCldlIHdvdWxkIGFsc28gZXhwZWN0IHRoZSBwb3B1bGF0aW9uIGRlbnNpdHkgZGF0YSBtaWdodCBjb3JyZWxhdGUgd2l0aCBzb21lIG9mIHRoZXNlIHZhcmlhYmxlcy4gDQpMZXQncyB0YWtlIGEgbG9vay4NCg0KYGBge3J9DQpwbSAlPiUNCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIHBvcGRlbnNfY291bnR5LCANCiAgICAgICBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCkgJT4lDQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCAgaGp1c3QgPSAuODUsIHNpemUgPSAzLA0KICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQ0KDQpwbSAlPiUNCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIHBvcGRlbnNfY291bnR5LCANCiAgICAgICBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCwgY291bnR5X3BvcCkgJT4lDQogIGdncGFpcnMoKQ0KYGBgDQoNCg0KSW50ZXJlc3RpbmcsIHNvIHRoZXNlIHZhcmlhYmxlcyBkb24ndCBhcHBlYXIgdG8gYmUgaGlnaGx5IGNvcnJlbGF0ZWQsIHRoZXJlZm9yZSB3ZSBtaWdodCBuZWVkIHZhcmlhYmxlcyBmcm9tIGVhY2ggb2YgdGhlIGNhdGVnb3JpZXMgdG8gcHJlZGljdCBvdXIgbW9uaXRvciBQTX4yLjV+IHBvbGx1dGlvbiB2YWx1ZXMuDQoNCkJlY2F1c2Ugc29tZSB2YXJpYWJsZXMgaW4gb3VyIGRhdGEgaGF2ZSBleHRyZW1lIHZhbHVlcywgaXQgbWlnaHQgYmUgZ29vZCB0byB0YWtlIGEgbG9nIHRyYW5zZm9ybWF0aW9uLiBUaGlzIGNhbiBhZmZlY3Qgb3VyIGVzdGltYXRlcyBvZiBjb3JyZWxhdGlvbi4gDQpgYGB7cn0NCnBtICU+JQ0KICBtdXRhdGUobG9nX3BvcGRlbnNfY291bnR5PSBsb2cocG9wZGVuc19jb3VudHkpKSAlPiUNCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIGxvZ19wb3BkZW5zX2NvdW50eSwgDQogICAgICAgbG9nX3ByaV9sZW5ndGhfMTAwMDAsIGltcF9hMTAwMDApICU+JQ0KICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgIGhqdXN0ID0gLjg1LCBzaXplID0gMywNCiAgICAgICBsYXlvdXQuZXhwPTIsIGxhYmVsID0gVFJVRSkNCg0KcG0gJT4lDQogIG11dGF0ZShsb2dfcG9wZGVuc19jb3VudHk9IGxvZyhwb3BkZW5zX2NvdW50eSkpICU+JQ0KICBtdXRhdGUobG9nX3BvcF9jb3VudHkgPSBsb2coY291bnR5X3BvcCkpICU+JQ0Kc2VsZWN0KGxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCwgbG9nX3BvcGRlbnNfY291bnR5LCANCiAgICAgICBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCwgbG9nX3BvcF9jb3VudHkpICU+JQ0KICBnZ3BhaXJzKCkNCmBgYA0KDQpJbmRlZWQgdGhpcyBpbmNyZWFzZWQgdGhlIGNvcnJlbGF0aW9uLCBidXQgdmFyaWFibGVzIGZyb20gZWFjaCBvZiB0aGVzZSBjYXRlZ29yaWVzIG1heSBzdGlsbCBwcm92ZSB0byBiZSB1c2VmdWwgZm9yIHByZWRpY3Rpb24uDQoNCk5vdyB0aGF0IHdlIGhhdmUgYSBzZW5zZSBvZiB3aGF0IG91ciBkYXRhIGFyZSwgd2UgY2FuIGdldCBzdGFydGVkIHdpdGggYnVpbGRpbmcgYSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVsIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbi4gDQoNCiMjICoqRXhlcmNpc2UqKg0KKioqDQoNCjwhLS0tQVBfREVXX1F1aXotLT4NCg0KPGlmcmFtZSBzdHlsZT0ibWFyZ2luOjAgYXV0bzsgbWluLXdpZHRoOiAxMDAlOyIgaWQ9IkFQX0RFV19RdWl6SWZyYW1lIiBjbGFzcz0iaW50ZXJhY3RpdmUiIHNyYz0iaHR0cHM6Ly9yc2Nvbm5lY3QuYmlvc3RhdC5qaHNwaC5lZHUvT0NTX0FQX0RFV19RdWl6LyIgc2Nyb2xsaW5nPSJubyIgZnJhbWVib3JkZXI9Im5vIj48L2lmcmFtZT4NCg0KPCEtLS0tLS0tLS0tLS0tLS0tPg0KDQpTdXBwb3NlIHdlIGhhdmUgYSBkYXRhZnJhbWUgY2FsbGVkIGBteWRhdGFgLiBUaGVyZSBhcmUgZml2ZSB2YXJpYWJsZXMgaW4gdGhpcyBkYXRhZnJhbWU6IGB2YXIxYCwgYHZhcjJgLCBgdmFyM2AsIGB2YXI0YCwgYW5kIGB2YXI1YC4gVHJ5IHRvIGNvbWUgdXAgd2l0aCB0aGUgY29kZSBmb3IgY3JlYXRpbmcgdGhlIHBsb3QgY2FsbGVkIGBteXBsb3RgLiBUaGlzIHBsb3QgdmlzdWFsaXplcyBjb3JyZWxhdGlvbnMgYmV0d2VlbiB2YXJpYWJsZXMuIChIaW50OiBzdGFydCBmcm9tIGBteWRhdGFgIGFuZCB1c2UgYSBmdW5jdGlvbiBmcm9tIHRoZSBHR2FsbHkgcGFja2FnZSkNCg0KPCEtLS1BUF9ERVdfRXhlcmNpc2UxLS0+DQoNCjxpZnJhbWUgc3R5bGU9Im1hcmdpbjowIGF1dG87IG1pbi13aWR0aDogMTAwJTsiIGlkPSJBUF9ERVdfRXhlcmNpc2UxSWZyYW1lIiBjbGFzcz0iaW50ZXJhY3RpdmUiIHNyYz0iaHR0cHM6Ly9yc2Nvbm5lY3QuYmlvc3RhdC5qaHNwaC5lZHUvT0NTX0FQX0RFV19FeGVyY2lzZS8iIHNjcm9sbGluZz0ibm8iIGZyYW1lYm9yZGVyPSJubyI+PC9pZnJhbWU+DQoNCjwhLS0tLS0tLS0tLS0tLS0tLT4NCg0KIyAqKldoYXQgaXMgbWFjaGluZSBsZWFybmluZz8qKiAgeyN3aGF0aXNtbH0NCioqKg0KDQpZb3UgbWF5IGhhdmUgbGVhcm5lZCBhYm91dCB0aGUgY2VudHJhbCBkb2dtYSBvZiBzdGF0aXN0aWNzIHRoYXQgeW91IHNhbXBsZSBmcm9tIGEgcG9wdWxhdGlvbi4NCg0KIVtdKGltZy9jZGkxLnBuZykNCg0KVGhlbiB5b3UgdXNlIHRoZSBzYW1wbGUgdG8gdHJ5IHRvIGd1ZXNzIHdoYXQgaXMgaGFwcGVuaW5nIGluIHRoZSBwb3B1bGF0aW9uLg0KDQohW10oaW1nL2NkaTIucG5nKQ0KDQpGb3IgcHJlZGljdGlvbiB3ZSBoYXZlIGEgc2ltaWxhciBzYW1wbGluZyBwcm9ibGVtDQoNCiFbXShpbWcvY2RwMS5wbmcpDQoNCkJ1dCBub3cgd2UgYXJlIHRyeWluZyB0byBidWlsZCBhIHJ1bGUgdGhhdCBjYW4gYmUgdXNlZCB0byBwcmVkaWN0IGEgc2luZ2xlIG9ic2VydmF0aW9uJ3MgdmFsdWUgb2Ygc29tZSBjaGFyYWN0ZXJpc3RpYyB1c2luZyBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIG90aGVyIG9ic2VydmF0aW9ucy4gDQoNCiFbXShpbWcvY2RwMi5wbmcpDQoNCkxldCdzIG1ha2UgdGhpcyBtb3JlIGNvbmNyZXRlLg0KDQpJZiB5b3UgcmVjYWxsIGZyb20gdGhlIFtXaGF0IGFyZSB0aGUgZGF0YT9dKCN3aGF0YXJldGhlZGF0YSkgc2VjdGlvbiBhYm92ZSwgd2hlbiB3ZSBhcmUgdXNpbmcgbWFjaGluZSBsZWFybmluZyBmb3IgcHJlZGljdGlvbiwgb3VyIGRhdGEgY29uc2lzdHMgb2Y6IA0KDQoxLiBBbiAqKmNvbnRpbnVvdXMqKiBvdXRjb21lIHZhcmlhYmxlIHRoYXQgd2Ugd2FudCB0byBwcmVkaWN0IA0KMi4gQSBzZXQgb2YgZmVhdHVyZShzKSAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykgdGhhdCB3ZSB1c2UgdG8gcHJlZGljdCB0aGUgb3V0Y29tZSB2YXJpYWJsZQ0KDQpXZSB3aWxsIHVzZSAkWSQgdG8gZGVub3RlIHRoZSBvdXRjb21lIHZhcmlhYmxlIGFuZCAkWCA9IChYXzEsIFxkb3RzLCBYX3ApJCB0byBkZW5vdGUgJHAkIGRpZmZlcmVudCBmZWF0dXJlcyAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykuIA0KQmVjYXVzZSBvdXIgb3V0Y29tZSB2YXJpYWJsZSBpcyAqKmNvbnRpbnVvdXMqKiAoYXMgb3Bwb3NlZCB0byBjYXRlZ29yaWNhbCksIHdlIGFyZSBpbnRlcmVzdGVkIGluIGEgcGFydGljdWxhciB0eXBlIG9mIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtLiANCg0KT3VyIGdvYWwgaXMgdG8gYnVpbGQgYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSB0aGF0IHVzZXMgdGhlIGZlYXR1cmVzICRYJCBhcyBpbnB1dCBhbmQgcHJlZGljdHMgYW4gb3V0Y29tZSB2YXJpYWJsZSAob3IgYWlyIHBvbGx1dGlvbiBsZXZlbHMpIGluIHRoZSBzaXR1YXRpb24gd2hlcmUgd2UgZG8gbm90IGtub3cgdGhlIG91dGNvbWUgdmFyaWFibGUuIA0KDQpUaGUgd2F5IHdlIGRvIHRoaXMgaXMgdG8gdXNlIGRhdGEgd2hlcmUgd2UgaGF2ZSBib3RoIHRoZSBmZWF0dXJlcyAkKFhfMT14XzEsIFxkb3RzIFhfcD14X3ApJCBhbmQgdGhlIGFjdHVhbCBvdXRjb21lICRZJCBkYXRhIHRvIF90cmFpbl8gYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSB0byBwcmVkaWN0IHRoZSBvdXRjb21lLCB3aGljaCB3ZSBjYWxsICRcaGF0e1l9JC4gIA0KDQpXaGVuIHdlIHNheSB0cmFpbiBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtIHdlIG1lYW4gdGhhdCB3ZSBlc3RpbWF0ZSBhIGZ1bmN0aW9uICRmJCB0aGF0IHVzZXMgdGhlIHByZWRpY3RvciB2YXJpYWJsZXMgJFgkIGFzIGlucHV0IG9yICRcaGF0e1l9ID0gZihYKSQuIA0KDQojIyAqKk1MIGFzIGFuIG9wdGltaXphdGlvbiBwcm9ibGVtKioNCg0KSWYgd2UgYXJlIGRvaW5nIGEgZ29vZCBqb2IsIHRoZW4gb3VyIHByZWRpY3RlZCBvdXRjb21lICRcaGF0e1l9JCBzaG91bGQgY2xvc2VseSBtYXRjaCBvdXIgYWN0dWFsIG91dGNvbWUgJFkkIHRoYXQgd2Ugb2JzZXJ2ZWQuIA0KDQpJbiB0aGlzIHdheSwgd2UgY2FuIHRoaW5rIG9mIG1hY2hpbmUgbGVhcm5pbmcgKE1MKSBhcyBhbiBvcHRpbWl6YXRpb24gcHJvYmxlbSB0aGF0IHRyaWVzIHRvIG1pbmltaXplIHRoZSBkaXN0YW5jZSBiZXR3ZWVuICRcaGF0e1l9ID0gZihYKSQgYW5kICRZJC4gDQoNCiQkZChZIC0gZihYKSkkJA0KVGhlIGNob2ljZSBvZiBkaXN0YW5jZSBtZXRyaWMgJGQoXGNkb3QpJCBjYW4gYmUgdGhlIG1lYW4gb2YgdGhlIGFic29sdXRlIG9yIHNxdWFyZWQgZGlmZmVyZW5jZSBvciBzb21ldGhpbmcgbW9yZSBjb21wbGljYXRlZC4gDQoNCk11Y2ggb2YgdGhlIGZpZWxkcyBvZiBzdGF0aXN0aWNzIGFuZCBjb21wdXRlciBzY2llbmNlIGFyZSBmb2N1c2VkIG9uIGRlZmluaW5nICRmJCBhbmQgJGQkLg0KDQojIyAqKlRoZSBwYXJ0cyBvZiBhbiBNTCBwcm9ibGVtKioNCg0KVG8gc2V0IHVwIGEgbWFjaGluZSBsZWFybmluZyAoTUwpIHByb2JsZW0sIHdlIG5lZWQgYSBmZXcgY29tcG9uZW50cy4NClRvIHNvbHZlIGEgKHN0YW5kYXJkKSBtYWNoaW5lIGxlYXJuaW5nIHByb2JsZW0geW91IG5lZWQ6IA0KDQoxLiBBIGRhdGEgc2V0IHRvIHRyYWluIGZyb20uIA0KMi4gQW4gYWxnb3JpdGhtIG9yIHNldCBvZiBhbGdvcml0aG1zIHlvdSBjYW4gdXNlIHRvIHRyeSB2YWx1ZXMgb2YgJGYkDQozLiBBIGRpc3RhbmNlIG1ldHJpYyAkZCQgZm9yIG1lYXN1cmluZyBob3cgY2xvc2UgJFkkIGlzIHRvICRcaGF0e1l9JA0KNC4gQSBkZWZpbml0aW9uIG9mIHdoYXQgYSAiZ29vZCIgZGlzdGFuY2UgaXMNCg0KV2hpbGUgZWFjaCBvZiB0aGVzZSBjb21wb25lbnRzIGlzIGEgX3RlY2huaWNhbF8gcHJvYmxlbSwgdGhlcmUgaGFzIGJlZW4gYSB0b24gb2Ygd29yayBhZGRyZXNzaW5nIHRob3NlIHRlY2huaWNhbCBkZXRhaWxzLiBUaGUgbW9zdCBwcmVzc2luZyBvcGVuIGlzc3VlIGluIG1hY2hpbmUgbGVhcm5pbmcgaXMgcmVhbGl6aW5nIHRoYXQgdGhvdWdoIHRoZXNlIGFyZSBfdGVjaG5pY2FsXyBzdGVwcyB0aGV5IGFyZSBub3QgX29iamVjdGl2ZV8gc3RlcHMuIEluIG90aGVyIHdvcmRzLCBob3cgeW91IGNob29zZSB0aGUgZGF0YSwgYWxnb3JpdGhtLCBtZXRyaWMsIGFuZCBkZWZpbml0aW9uIG9mICJnb29kIiBzYXlzIHdoYXQgeW91IHZhbHVlIGFuZCBjYW4gZHJhbWF0aWNhbGx5IGNoYW5nZSB0aGUgcmVzdWx0cy4gQSBjb3VwbGUgb2YgY2FzZXMgd2hlcmUgdGhpcyB3YXMgYSBiaWcgZGVhbCBhcmU6IA0KDQoxLiBbTWFjaGluZSBsZWFybmluZyBmb3IgcmVjaWRpdmlzbV0oaHR0cHM6Ly93d3cucHJvcHVibGljYS5vcmcvYXJ0aWNsZS9tYWNoaW5lLWJpYXMtcmlzay1hc3Nlc3NtZW50cy1pbi1jcmltaW5hbC1zZW50ZW5jaW5nKSAtIHBlb3BsZSBidWlsdCBNTCBtb2RlbHMgdG8gcHJlZGljdCB3aG8gd291bGQgcmUtY29tbWl0IGEgY3JpbWUuIEJ1dCB0aGVzZSBwcmVkaWN0aW9ucyB3ZXJlIGJhc2VkIG9uIGhpc3RvcmljYWxseSBiaWFzZWQgZGF0YSB3aGljaCBsZWQgdG8gYmlhc2VkIHByZWRpY3Rpb25zIGFib3V0IHdobyB3b3VsZCBjb21taXQgbmV3IGNyaW1lcy4gDQoyLiBbRGVjaWRpbmcgaG93IHNlbGYgZHJpdmluZyBjYXJzIHNob3VsZCBhY3RdKGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvZDQxNTg2LTAxOC0wNzEzNS0wKSAtIHNlbGYgZHJpdmluZyBjYXJzIHdpbGwgaGF2ZSB0byBtYWtlIGRlY2lzaW9ucyBhYm91dCBob3cgdG8gZHJpdmUsIHdobyB0aGV5IG1pZ2h0IGluanVyZSwgYW5kIGhvdyB0byBhdm9pZCBhY2NpZGVudHMuIERlcGVuZGluZyBvbiBvdXIgY2hvaWNlcyBmb3IgJGYkIGFuZCAkZCQgdGhlc2UgbWlnaHQgbGVhZCB0byB3aWxkbHkgZGlmZmVyZW50IGtpbmRzIG9mIHNlbGYgZHJpdmluZyBjYXJzLiBUcnkgb3V0IHRoZSBbbW9yYWxtYWNoaW5lXShodHRwOi8vbW9yYWxtYWNoaW5lLm1pdC5lZHUvKSB0byBzZWUgaG93IHRoaXMgbG9va3MgaW4gcHJhY3RpY2UuIA0KDQpOb3cgdGhhdCB3ZSBrbm93IGEgYml0IG1vcmUgYWJvdXQgbWFjaGluZSBsZWFybmluZywgbGV0J3MgYnVpbGQgYSBtb2RlbCB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIHVzaW5nIHRoZSBgdGlkeW1vZGVsc2AgZnJhbWV3b3JrLiANCg0KIyAqKk1hY2hpbmUgbGVhcm5pbmcgd2l0aCBgdGlkeW1vZGVsc2AqKg0KKioqDQpUaGUgZ29hbCBpcyB0byBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtIHRoYXQgdXNlcyB0aGUgZmVhdHVyZXMgYXMgaW5wdXQgYW5kIHByZWRpY3RzIGEgb3V0Y29tZSB2YXJpYWJsZSAob3IgYWlyIHBvbGx1dGlvbiBsZXZlbHMpIGluIHRoZSBzaXR1YXRpb24gd2hlcmUgd2UgZG8gbm90IGtub3cgdGhlIG91dGNvbWUgdmFyaWFibGUuIA0KDQpUaGUgd2F5IHdlIGRvIHRoaXMgaXMgdG8gdXNlIGRhdGEgd2hlcmUgd2UgaGF2ZSBib3RoIHRoZSBpbnB1dCBhbmQgb3V0cHV0IGRhdGEgdG8gX3RyYWluXyBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtLiANCg0KVG8gdHJhaW4gYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSwgd2Ugd2lsbCB1c2UgdGhlIGB0aWR5bW9kZWxzYCBwYWNrYWdlIGVjb3N5c3RlbS4gDQoNCiMjICoqT3ZlcnZpZXcqKg0KKioqDQoNCiMjIyAqKlRoZSBgdGlkeW1vZGVsc2AgZWNvc3lzdGVtKioNCioqKg0KDQpUbyBwZXJmb3JtIG91ciBhbmFseXNpcyB3ZSB3aWxsIGJlIHVzaW5nIHRoZSBgdGlkeW1vZGVsc2Agc3VpdGUgb2YgcGFja2FnZXMuIA0KWW91IG1heSBiZSBmYW1pbGlhciB3aXRoIHRoZSBvbGRlciBwYWNrYWdlcyBgY2FyZXRgIG9yIGBtbHJgIHdoaWNoIGFyZSBhbHNvIGZvciBtYWNoaW5lIGxlYXJuaW5nIGFuZCBtb2RlbGluZyBidXQgYXJlIG5vdCBhIHBhcnQgb2YgdGhlIGB0aWR5dmVyc2VgLiANCltNYXggS3Vobl0oaHR0cHM6Ly9yZXNvdXJjZXMucnN0dWRpby5jb20vYXV0aG9ycy9tYXgta3Vobil7dGFyZ2V0PSJfYmxhbmsifSBkZXNjcmliZXMgYHRpZHltb2RlbHNgIGxpa2UgdGhpczoNCg0KPiAiT3RoZXIgcGFja2FnZXMsIHN1Y2ggYXMgY2FyZXQgYW5kIG1sciwgaGVscCB0byBzb2x2ZSB0aGUgUiBtb2RlbCBBUEkgaXNzdWUuIFRoZXNlIHBhY2thZ2VzIGRvIGEgbG90IG9mIG90aGVyIHRoaW5ncyB0b286IHByZS1wcm9jZXNzaW5nLCBtb2RlbCB0dW5pbmcsIHJlc2FtcGxpbmcsIGZlYXR1cmUgc2VsZWN0aW9uLCBlbnNlbWJsaW5nLCBhbmQgc28gb24uIEluIHRoZSB0aWR5dmVyc2UsIHdlIHN0cml2ZSB0byBtYWtlIG91ciBwYWNrYWdlcyBtb2R1bGFyIGFuZCBwYXJzbmlwIGlzIGRlc2lnbmVkIG9ubHkgdG8gc29sdmUgdGhlIGludGVyZmFjZSBpc3N1ZS4gSXQgaXMgbm90IGRlc2lnbmVkIHRvIGJlIGEgZHJvcC1pbiByZXBsYWNlbWVudCBmb3IgY2FyZXQuDQpUaGUgdGlkeW1vZGVscyBwYWNrYWdlIGNvbGxlY3Rpb24sIHdoaWNoIGluY2x1ZGVzIHBhcnNuaXAsIGhhcyBvdGhlciBwYWNrYWdlcyBmb3IgbWFueSBvZiB0aGVzZSB0YXNrcywgYW5kIHRoZXkgYXJlIGRlc2lnbmVkIHRvIHdvcmsgdG9nZXRoZXIuIFdlIGFyZSB3b3JraW5nIHRvd2FyZHMgaGlnaGVyLWxldmVsIEFQSXMgdGhhdCBjYW4gcmVwbGljYXRlIGFuZCBleHRlbmQgd2hhdCB0aGUgY3VycmVudCBtb2RlbCBwYWNrYWdlcyBjYW4gZG8uIg0KDQpUaGVyZSBhcmUgbWFueSBSIHBhY2thZ2VzIGluIHRoZSBgdGlkeW1vZGVsc2AgZWNvc3lzdGVtLCB3aGljaCBhc3Npc3Qgd2l0aCB2YXJpb3VzIHN0ZXBzIGluIHRoZSBwcm9jZXNzIG9mIGJ1aWxkaW5nIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0uIFRoZXNlIGFyZSB0aGUgbWFpbiBwYWNrYWdlcywgYnV0IHRoZXJlIGFyZSBvdGhlcnMuDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInNpbXBsZXRpZHltb2RlbHMucG5nIikpDQpgYGANCg0KVGhpcyBpcyBhIHNjaGVtYXRpYyBvZiBob3cgdGhlc2UgcGFja2FnZXMgd29yayB0b2dldGhlciB0byBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtOg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJNYWNoaW5lTGVhcm5pbmcucG5nIikpDQpgYGANCg0KIyMjICoqQmVuZWZpdHMgb2YgYHRpZHltb2RlbHNgKioNCioqKg0KDQpUaGUgdHdvIG1ham9yIGJlbmVmaXRzIG9mIGB0aWR5bW9kZWxzYCBhcmU6IA0KDQoxLiBTdGFuZGFyZGl6ZWQgd29ya2Zsb3cvZm9ybWF0L25vdGF0aW9uIGFjcm9zcyBkaWZmZXJlbnQgdHlwZXMgb2YgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG1zICANCg0KRGlmZmVyZW50IG5vdGF0aW9ucyBhcmUgcmVxdWlyZWQgZm9yIGRpZmZlcmVudCBhbGdvcml0aG1zIGFzIHRoZSBhbGdvcml0aG1zIGhhdmUgYmVlbiBkZXZlbG9wZWQgYnkgZGlmZmVyZW50IHBlb3BsZS4gVGhpcyB3b3VsZCByZXF1aXJlIHRoZSBwYWluc3Rha2luZyBwcm9jZXNzIG9mIHJlZm9ybWF0dGluZyB0aGUgZGF0YSB0byBiZSBjb21wYXRpYmxlIHdpdGggZWFjaCBhbGdvcml0aG0gaWYgbXVsdGlwbGUgYWxnb3JpdGhtcyB3ZXJlIHRlc3RlZC4NCg0KMi4gQ2FuIGVhc2lseSBtb2RpZnkgcHJlLXByb2Nlc3NpbmcsIGFsZ29yaXRobSBjaG9pY2UsIGFuZCBoeXBlci1wYXJhbWV0ZXIgdHVuaW5nIG1ha2luZyBvcHRpbWl6YXRpb24gZWFzeSAgDQoNCk1vZGlmeWluZyBhIHBpZWNlIG9mIHRoZSBvdmVyYWxsIHByb2Nlc3MgaXMgbm93IGVhc2llciB0aGFuIGJlZm9yZSBiZWNhdXNlIG1hbnkgb2YgdGhlIHN0ZXBzIGFyZSBzcGVjaWZpZWQgdXNpbmcgdGhlIGB0aWR5bW9kZWxzYCBwYWNrYWdlcyBpbiBhIGNvbnZlbmllbnQgbWFubmVyLiBUaHVzIHRoZSBlbnRpcmUgcHJvY2VzcyBjYW4gYmUgcmVydW4gYWZ0ZXIgYSBzaW1wbGUgY2hhbmdlIHRvIHByZS1wcm9jZXNzaW5nIHdpdGhvdXQgbXVjaCBkaWZmaWN1bHR5Lg0KDQojIyAqKmB0aWR5bW9kZWxzYCBTdGVwcyoqDQoqKioNCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwidGlkeW1vZGVsc0Jhc2ljcy5wbmciKSkNCmBgYA0KDQojIyAqKlNwbGl0dGluZyB0aGUgZGF0YSoqDQoqKioNCg0KVGhlIGZpcnN0IHN0ZXAgYWZ0ZXIgZGF0YSBleHBsb3JhdGlvbiBpbiBtYWNoaW5lIGxlYXJuaW5nIGFuYWx5c2lzIGlzIHRvIFtzcGxpdCB0aGUgZGF0YV0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3RyYWluLXZhbGlkYXRpb24tYW5kLXRlc3Qtc2V0cy03MmNiNDBjYmE5ZTcpe3RhcmdldD0iX2JsYW5rIn0gaW50byAqKnRyYWluaW5nKiogYW5kICoqdGVzdGluZyoqIGRhdGEgc2V0cy4gDQoNClRoZSB0cmFpbmluZyBkYXRhIHNldCB3aWxsIGJlIHVzZWQgdG8gYnVpbGQgYW5kIHR1bmUgb3VyIG1vZGVsLiANClRoaXMgaXMgdGhlIGRhdGEgdGhhdCB0aGUgbW9kZWwgImxlYXJucyIgb24uIA0KVGhlIHRlc3RpbmcgZGF0YSBzZXQgd2lsbCBiZSB1c2VkIHRvIGV2YWx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiBvdXIgbW9kZWwgaW4gYSBtb3JlIGdlbmVyYWxpemFibGUgd2F5LiBXaGF0IGRvIHdlIG1lYW4gYnkgImdlbmVyYWxpemFibGUiPw0KDQpSZW1lbWJlciB0aGF0IG91ciBtYWluIGdvYWwgaXMgdG8gdXNlIG91ciBtb2RlbCB0byBiZSBhYmxlIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiBsZXZlbHMgaW4gYXJlYXMgd2hlcmUgdGhlcmUgYXJlIG5vIGdyYXZpbWV0cmljIG1vbml0b3JzLiANCg0KVGhlcmVmb3JlLCBpZiBvdXIgbW9kZWwgaXMgcmVhbGx5IGdvb2QgYXQgcHJlZGljdGluZyBhaXIgcG9sbHV0aW9uIHdpdGggdGhlIGRhdGEgdGhhdCB3ZSB1c2UgdG8gYnVpbGQgaXQsIGl0IG1pZ2h0IG5vdCBkbyB0aGUgYmVzdCBqb2IgZm9yIHRoZSBhcmVhcyB3aGVyZSB0aGVyZSBhcmUgZmV3IHRvIG5vIG1vbml0b3JzLiANCg0KVGhpcyB3b3VsZCBjYXVzZSB1cyB0byBoYXZlIHJlYWxseSBnb29kIHByZWRpY3Rpb24gYWNjdXJhY3kgYW5kIHdlIG1pZ2h0IGFzc3VtZSB0aGF0IHdlIHdlcmUgZ29pbmcgdG8gZG8gYSBnb29kIGpvYiBlc3RpbWF0aW5nIGFpciBwb2xsdXRpb24gYW55IHRpbWUgd2UgdXNlIG91ciBtb2RlbCwgYnV0IGluIGZhY3QgdGhpcyB3b3VsZCBsaWtlbHkgbm90IGJlIHRoZSBjYXNlLiANClRoaXMgc2l0dWF0aW9uIGlzIHdoYXQgd2UgY2FsbCAqKltvdmVyZml0dGluZ10oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3RyYWluLXRlc3Qtc3BsaXQtYW5kLWNyb3NzLXZhbGlkYXRpb24taW4tcHl0aG9uLTgwYjYxYmVjYTRiNil7dGFyZ2V0PSJfYmxhbmsifSAqKi4NCg0KT3ZlcmZpdHRpbmcgaGFwcGVucyB3aGVuIHdlIGVuZCB1cCBtb2RlbGluZyBub3Qgb25seSB0aGUgbWFqb3IgcmVsYXRpb25zaGlwcyBpbiBvdXIgZGF0YSBidXQgYWxzbyB0aGUgbm9pc2Ugd2l0aGluIG91ciBkYXRhLiANCg0KYGBge3IsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9taXJvLm1lZGl1bS5jb20vbWF4LzExMTAvMSp0QkVyWFlWdlR3MmpTVVlLN3RoVTJBLnBuZyIpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL21pcm8ubWVkaXVtLmNvbS9tYXgvMTExMC8xKnRCRXJYWVZ2VHcyalNVWUs3dGhVMkEucG5nKXt0YXJnZXQ9Il9ibGFuayJ9DQoNCklmIHdlIGdldCBnb29kIHByZWRpY3Rpb24gd2l0aCBvdXIgdGVzdGluZyBzZXQsIHRoZW4gd2Uga25vdyB0aGF0IG91ciBtb2RlbCBjYW4gYmUgYXBwbGllZCB0byBvdGhlciBkYXRhIGFuZCB3aWxsIGxpa2VseSBwZXJmb3JtIHdlbGwuIFdlIHdpbGwgZGlzY3VzcyB0aGlzIG1vcmUgbGF0ZXIuDQoNCldlIHdpbGwgbm90IHRvdWNoIHRoZSB0ZXN0aW5nIHNldCB1bnRpbCB3ZSBoYXZlIGNvbXBsZXRlZCBvcHRpbWl6aW5nIG91ciBtb2RlbCB3aXRoIHRoZSB0cmFpbmluZyBzZXQuIA0KVGhpcyB3aWxsIGFsbG93IHVzIHRvIGhhdmUgYSBsZXNzIGJpYXNlZCBldmFsdWF0aW9uIG9mIGhvdyB3ZWxsIG91ciBtb2RlbCBjYW4gZG8gd2l0aCBvdGhlciBkYXRhIGJlc2lkZXMgdGhlIGRhdGEgdXNlZCBpbiB0aGUgdHJhaW5pbmcgc2V0IHRvIGJ1aWxkIHRoZSBtb2RlbC4gDQpJZGVhbGx5LCB5b3Ugd291bGQgYWxzbyB3YW50IGEgY29tcGxldGVseSBpbmRlcGVuZGVudCBkYXRhIHNldCB0byBmdXJ0aGVyIHRlc3QgdGhlIHBlcmZvcm1hbmNlIG9mIHlvdXIgbW9kZWwuDQoNClRvIHNwbGl0IHRoZSBkYXRhIGludG8gdHJhaW5pbmcgYW5kIHRlc3RpbmcsIHdlIHdpbGwgdXNlIHRoZSBgaW5pdGlhbF9zcGxpdCgpYCBmdW5jdGlvbiBpbiB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgdG8gc3BlY2lmeSBob3cgd2Ugd2FudCB0byBzcGxpdCBvdXIgZGF0YS4NCg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCg0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwic3BsaXQucG5nIikpDQpgYGANCg0KYGBge3J9DQpzZXQuc2VlZCgxMjM0KQ0KcG1fc3BsaXQgPC0gcnNhbXBsZTo6aW5pdGlhbF9zcGxpdChkYXRhID0gcG0sIHByb3AgPSAyLzMpDQpwbV9zcGxpdA0KYGBgDQoNCkEgY291cGxlIG9mIG5vdGVzIGZyb20gdGhlIGNvZGUgYWJvdmU6IA0KDQotIFR5cGljYWxseSwgZGF0YSBhcmUgc3BsaXQgaW50byAzLzQgb2YgdGhlIG9ic2VydmF0aW9ucyBmb3IgdHJhaW5pbmcgYW5kIDEvNCBmb3IgdGVzdGluZy4gVGhpcyBpcyB0aGUgZGVmYXVsdCBwcm9wb3J0aW9uIGFuZCBkb2VzIG5vdCBuZWVkIHRvIGJlIHNwZWNpZmllZC4gSG93ZXZlciwgeW91IGNhbiBjaGFuZ2UgdGhlIHByb3BvcnRpb24gdXNpbmcgdGhlIGBwcm9wYCBhcmd1bWVudCwgd2hpY2ggd2Ugd2lsbCBkbyB0aGF0IGhlcmUgZm9yIGlsbHVzdHJhdGl2ZSBwdXJwb3Nlcy4NCi0gU2luY2UgdGhlIHNwbGl0IGlzIHBlcmZvcm1lZCByYW5kb21seSwgaXQgaXMgYSBnb29kIGlkZWEgdG8gdXNlIHRoZSBgc2V0LnNlZWQoKWAgZnVuY3Rpb24gaW4gYmFzZSBSIHRvIGVuc3VyZSB0aGF0IGlmIHlvdXIgcmVydW4geW91ciBjb2RlIHRoYXQgeW91ciBzcGxpdCB3aWxsIGJlIHRoZSBzYW1lIG5leHQgdGltZS4NCi0gV2UgY2FuIHNlZSB0aGUgbnVtYmVyIG9mIG1vbml0b3JzIGluIG91ciB0cmFpbmluZywgdGVzdGluZywgYW5kIG9yaWdpbmFsIGRhdGEgYnkgdHlwaW5nIGluIHRoZSBuYW1lIG9mIG91ciBzcGxpdCBvYmplY3QuIFRoZSByZXN1bHQgd2lsbCBsb29rIGxpa2UgdGhpczoNCjx0cmFpbmluZyBkYXRhIHNhbXBsZSBudW1iZXIsIHRlc3RpbmcgZGF0YSBzYW1wbGUgbnVtYmVyLCBvcmlnaW5hbCBzYW1wbGUgbnVtYmVyPiANCg0KTm93LCB5b3UgY2FuIGFsc28gc3BlY2lmeSBhIHZhcmlhYmxlIHRvIHN0cmF0aWZ5IGJ5IHdpdGggdGhlIGBzdHJhdGFgIGFyZ3VtZW50LiANClRoaXMgaXMgdXNlZnVsIGlmIHlvdSBoYXZlIGltYmFsYW5jZWQgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGFuZCB5b3Ugd291bGQgbGlrZSB0byBpbnRlbnRpb25hbGx5IG1ha2Ugc3VyZSB0aGF0IHRoZXJlIGFyZSBzaW1pbGFyIG51bWJlciBvZiBzYW1wbGVzIG9mIHRoZSByYXJlciBjYXRlZ29yaWVzIGluIGJvdGggdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIHNldHMuIA0KT3RoZXJ3aXNlIHRoZSBzcGxpdCBpcyBwZXJmb3JtZWQgcmFuZG9tbHkuIA0KDQpBY2NvcmRpbmcgdG8gdGhlIFtkb2N1bWVudGF0aW9uXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvcnNhbXBsZS92ZXJzaW9ucy8wLjAuNS90b3BpY3MvaW5pdGlhbF9zcGxpdCkgZm9yIHRoZSBgcnNhbXBsZWAgcGFja2FnZToNCg0KPiBUaGUgc3RyYXRhIGFyZ3VtZW50IGNhdXNlcyB0aGUgcmFuZG9tIHNhbXBsaW5nIHRvIGJlIGNvbmR1Y3RlZCB3aXRoaW4gdGhlIHN0cmF0aWZpY2F0aW9uIHZhcmlhYmxlLiBUaGlzIGNhbiBoZWxwIGVuc3VyZSB0aGF0IHRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgaW4gdGhlIHRyYWluaW5nIGRhdGEgaXMgZXF1aXZhbGVudCB0byB0aGUgcHJvcG9ydGlvbnMgaW4gdGhlIG9yaWdpbmFsIGRhdGEgc2V0Lg0KDQpJbiB0aGUgY2FzZSB3aXRoIG91ciBkYXRhIHNldCwgcGVyaGFwcyB3ZSB3b3VsZCBsaWtlIG91ciB0cmFpbmluZyBzZXQgdG8gaGF2ZSBzaW1pbGFyIHByb3BvcnRpb25zIG9mIG1vbml0b3JzIGZyb20gZWFjaCBvZiB0aGUgc3RhdGVzIGFzIGluIHRoZSBpbml0aWFsIGRhdGEuIA0KVGhpcyBtaWdodCBiZSB1c2VmdWwgaWYgd2Ugd2FudCBvdXIgbW9kZWwgdG8gYmUgZ2VuZXJhbGl6YWJsZSBhY3Jvc3MgYWxsIG9mIHRoZSBzdGF0ZXMuDQoNCldlIGNhbiBzZWUgdGhhdCBpbmRlZWQgdGhlcmUgYXJlIGRpZmZlcmVudCBwcm9wb3J0aW9ucyBvZiBtb25pdG9ycyBpbiBlYWNoIHN0YXRlIGJ5IHVzaW5nIHRoZSBgY291bnQoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gDQoNCmBgYHtyLCBldmFsID0gRkFMU0V9DQpjb3VudChwbSwgc3RhdGUpDQpgYGANCg0KU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dDoNCg0KIyMjIyB7LnNjcm9sbGFibGUgfQ0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCENCmNvdW50KHBtLCBzdGF0ZSkgJT4lDQogIHByaW50KG4gPSAxZTMpDQpgYGANCiMjIyMNCg0KSWYgb3VyIGRhdGEgc2V0IHdlcmUgbGFyZ2UgZW5vdWdoIGl0IG1pZ2h0IGJlIG5pY2UgdGhlbiB0byBzdHJhdGlmeSBieSBzdGF0ZSB1c2luZyB0aGUgYHN0cmF0YSA9ICJzdGF0ZSJgIGFyZ3VtZW50IGluIGBpbml0aWFsX3NwbGl0KClgLCBidXQgb3VyIGRhdGEgaXMgdW5mb3J0dW5hdGVseSBub3QgbGFyZ2UgZW5vdWdoLiANCg0KSW1wb3J0YW50bHkgdGhlIGBpbml0aWFsX3NwbGl0KClgIGZ1bmN0aW9uIG9ubHkgZGV0ZXJtaW5lcyB3aGF0IHJvd3Mgb2Ygb3VyIGBwbWAgZGF0YSBmcmFtZSBzaG91bGQgYmUgYXNzaWduZWQgZm9yIHRyYWluaW5nIG9yIHRlc3RpbmcsIGl0IGRvZXMgbm90IGFjdHVhbGx5IHNwbGl0IHRoZSBkYXRhLiANCg0KVG8gZXh0cmFjdCB0aGUgdGVzdGluZyBhbmQgdHJhaW5pbmcgZGF0YSB3ZSBjYW4gdXNlIHRoZSBgdHJhaW5pbmcoKWAgYW5kIGB0ZXN0aW5nKClgIGZ1bmN0aW9ucyBhbHNvIG9mIHRoZSBgcnNhbXBsZWAgcGFja2FnZS4NCg0KIyMjIyB7LnNjcm9sbGFibGUgfQ0KYGBge3J9DQp0cmFpbl9wbSA8LXJzYW1wbGU6OnRyYWluaW5nKHBtX3NwbGl0KQ0KdGVzdF9wbSA8LXJzYW1wbGU6OnRlc3RpbmcocG1fc3BsaXQpDQogDQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhDQpjb3VudCh0cmFpbl9wbSwgc3RhdGUpDQpjb3VudCh0ZXN0X3BtLCBzdGF0ZSkNCmBgYA0KIyMjIw0KDQoNCg0KIyMgKipQcmVwYXJpbmcgZm9yIHByZS1wcm9jZXNzaW5nIHRoZSBkYXRhKioNCioqKg0KDQpBZnRlciBzcGxpdHRpbmcgdGhlIGRhdGEsIHRoZSBuZXh0IHN0ZXAgaXMgdG8gcHJvY2VzcyB0aGUgdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YSBzbyB0aGF0IHRoZSBkYXRhIGFyZSBhcmUgY29tcGF0aWJsZSBhbmQgb3B0aW1pemVkIHRvIGJlIHVzZWQgd2l0aCB0aGUgbW9kZWwuIA0KVGhpcyBpbnZvbHZlcyBhc3NpZ25pbmcgdmFyaWFibGVzIHRvIHNwZWNpZmljIHJvbGVzIHdpdGhpbiB0aGUgbW9kZWwgYW5kIHByZS1wcm9jZXNzaW5nIGxpa2Ugc2NhbGluZyB2YXJpYWJsZXMgYW5kIHJlbW92aW5nIHJlZHVuZGFudCB2YXJpYWJsZXMuIA0KVGhpcyBwcm9jZXNzIGlzIGFsc28gY2FsbGVkIGZlYXR1cmUgZW5naW5lZXJpbmcuDQoNClRvIGRvIHRoaXMgaW4gYHRpZHltb2RlbHNgLCB3ZSB3aWxsIGNyZWF0ZSB3aGF0J3MgY2FsbGVkIGEgInJlY2lwZSIgdXNpbmcgdGhlIGByZWNpcGVzYCBwYWNrYWdlLCB3aGljaCBpcyBhIHN0YW5kYXJkaXplZCBmb3JtYXQgZm9yIGEgc2VxdWVuY2Ugb2Ygc3RlcHMgZm9yIHByZS1wcm9jZXNzaW5nIHRoZSBkYXRhLg0KVGhpcyBjYW4gYmUgdmVyeSB1c2VmdWwgYmVjYXVzZSBpdCBtYWtlcyB0ZXN0aW5nIG91dCBkaWZmZXJlbnQgcHJlLXByb2Nlc3Npbmcgc3RlcHMgb3IgZGlmZmVyZW50IGFsZ29yaXRobXMgd2l0aCB0aGUgc2FtZSBwcmUtcHJvY2Vzc2luZyB2ZXJ5IGVhc3kgYW5kIHJlcHJvZHVjaWJsZS4NCkNyZWF0aW5nIGEgcmVjaXBlIHNwZWNpZmllcyAqKmhvdyBhIGRhdGEgZnJhbWUgb2YgcHJlZGljdG9ycyBzaG91bGQgYmUgY3JlYXRlZCoqIC0gaXQgc3BlY2lmaWVzIHdoYXQgdmFyaWFibGVzIHRvIGJlIHVzZWQgYW5kIHRoZSBwcmUtcHJvY2Vzc2luZyBzdGVwcywgYnV0IGl0ICoqZG9lcyBub3QgZXhlY3V0ZSB0aGVzZSBzdGVwcyoqIG9yIGNyZWF0ZSB0aGUgZGF0YSBmcmFtZSBvZiBwcmVkaWN0b3JzLg0KDQojIyMgU3RlcCAxOiBTcGVjaWZ5IHZhcmlhYmxlcyByb2xlcyB3aXRoIGByZWNpcGUoKWAgZnVuY3Rpb24NCg0KVGhlIGZpcnN0IHRoaW5nIHRvIGRvIHRvIGNyZWF0ZSBhIHJlY2lwZSBpcyB0byBzcGVjaWZ5IHdoaWNoIHZhcmlhYmxlcyB3ZSB3aWxsIGJlIHVzaW5nIGFzIG91ciBvdXRjb21lIGFuZCBwcmVkaWN0b3JzIHVzaW5nIHRoZSBgcmVjaXBlKClgIGZ1bmN0aW9uLiANCkluIHRlcm1zIG9mIHRoZSBtZXRhcGhvciBvZiBiYWtpbmcsIHdlIGNhbiB0aGluayBvZiB0aGlzIGFzIGxpc3Rpbmcgb3VyIGluZ3JlZGllbnRzLiANClRyYW5zbGF0aW5nIHRoaXMgdG8gdGhlIGByZWNpcGVzYCBwYWNrYWdlLCB3ZSB1c2UgdGhlIGByZWNpcGUoKWAgZnVuY3Rpb24gdG8gYXNzaWduIHJvbGVzIHRvIGFsbCB0aGUgdmFyaWFibGVzLiANCg0KTGV0J3MgdHJ5IHRoZSBzaW1wbGVzdCByZWNpcGUgd2l0aCBubyBwcmUtcHJvY2Vzc2luZyBzdGVwczogc2ltcGx5IGxpc3QgdGhlIG91dGNvbWUgYW5kIHByZWRpY3RvciB2YXJpYWJsZXMuDQoNCldlIGNhbiBkbyBzbyBpbiB0d28gd2F5czogIA0KDQoxKSBVc2luZyBmb3JtdWxhIG5vdGF0aW9uICANCjIpIEFzc2lnbmluZyByb2xlcyB0byBlYWNoIHZhcmlhYmxlICANCg0KTGV0J3MgbG9vayBhdCB0aGUgZmlyc3Qgd2F5IHVzaW5nIGZvcm11bGEgbm90YXRpb24sIHdoaWNoIGxvb2tzIGxpa2UgdGhpczogIA0KDQpvdXRjb21lKHMpIH4gcHJlZGljdG9yKHMpICANCg0KSWYgaW4gdGhlIGNhc2Ugb2YgbXVsdGlwbGUgcHJlZGljdG9ycyBvciBhIG11bHRpdmFyaWF0ZSBzaXR1YXRpb24gd2l0aCB0d28gb3V0Y29tZXMsIHVzZSBhIHBsdXMgc2lnbjogIA0KDQpvdXRjb21lMSArIG91dGNvbWUyIH4gcHJlZGljdG9yMSArIHByZWRpY3RvcjIgIA0KDQpJZiB3ZSB3YW50IHRvIGluY2x1ZGUgYWxsIHByZWRpY3RvcnMgd2UgY2FuIHVzZSBhIHBlcmlvZCBsaWtlIHNvOiAgDQoNCm91dGNvbWVfdmFyaWFibGVfbmFtZSB+IC4gIA0KDQpOb3cgd2l0aCBvdXIgZGF0YSwgd2Ugd2lsbCBzdGFydCBieSBtYWtpbmcgYSByZWNpcGUgZm9yIG91ciB0cmFpbmluZyBkYXRhLg0KSWYgeW91IHJlY2FsbCwgdGhlIGNvbnRpbnVvdXMgb3V0Y29tZSB2YXJpYWJsZSBpcyBgdmFsdWVgICh0aGUgYXZlcmFnZSBhbm51YWwgZ3JhdmltZXRyaWMgbW9uaXRvciBQTX4yLjV+IGNvbmNlbnRyYXRpb24gaW4gdWcvbV4zXikuIA0KT3VyIGZlYXR1cmVzIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKSBhcmUgYWxsIHRoZSBvdGhlciB2YXJpYWJsZXMgZXhjZXB0IHRoZSBtb25pdG9yIElELCB3aGljaCBpcyBhbiBgaWRgIHZhcmlhYmxlLg0KDQpUaGUgcmVhc29uIG5vdCB0byBpbmNsdWRlIHRoZSBgaWRgIHZhcmlhYmxlIGlzIGJlY2F1c2UgdGhpcyB2YXJpYWJsZSBpbmNsdWRlcyB0aGUgY291bnR5IG51bWJlciBhbmQgYSBudW1iZXIgZGVzaWduYXRpbmcgd2hpY2ggcGFydGljdWxhciBtb25pdG9yIHRoZSB2YWx1ZXMgY2FtZSBmcm9tIChvZiB0aGUgbW9uaXRvcnMgdGhlcmUgYXJlIGluIHRoYXQgY291bnR5KS4gDQpTaW5jZSB0aGlzIG51bWJlciBpcyBhcmJpdHJhcnkgYW5kIHRoZSBjb3VudHkgaW5mb3JtYXRpb24gaXMgYWxzbyBnaXZlbiBpbiB0aGUgZGF0YSwgYW5kIHRoZSBmYWN0IHRoYXQgZWFjaCBtb25pdG9yIG9ubHkgaGFzIG9uZSB2YWx1ZSBpbiB0aGUgYHZhbHVlYCB2YXJpYWJsZSwgbm90aGluZyBpcyBnYWluZWQgYnkgaW5jbHVkaW5nIHRoaXMgdmFyaWFibGUgYW5kIGl0IG1heSBpbnN0ZWFkIGludHJvZHVjZSBub2lzZS4gDQpIb3dldmVyLCBpdCBpcyB1c2VmdWwgdG8ga2VlcCB0aGlzIGRhdGEgdG8gdGFrZSBhIGxvb2sgYXQgd2hhdCBpcyBoYXBwZW5pbmcgbGF0ZXIuIA0KV2Ugd2lsbCBzaG93IHlvdSB3aGF0IHRvIGRvIGluIHRoaXMgY2FzZSBpbiBqdXN0IGEgYml0Lg0KDQpJbiB0aGUgc2ltcGxlc3QgY2FzZSwgd2UgbWlnaHQgdXNlIGFsbCBwcmVkaWN0b3JzIGxpa2UgdGhpczoNCg0KYGBge3J9DQpzaW1wbGVfcmVjIDwtIHRyYWluX3BtICU+JQ0KICByZWNpcGVzOjpyZWNpcGUodmFsdWUgfiAuKQ0KDQpzaW1wbGVfcmVjDQpgYGANCg0KV2Ugc2VlIGEgcmVjaXBlIGhhcyBiZWVuIGNyZWF0ZWQgd2l0aCAxIG91dGNvbWUgdmFyaWFibGUgYW5kIDQ5IHByZWRpY3RvciB2YXJpYWJsZXMgKG9yIGZlYXR1cmVzKS4gDQpBbHNvLCBub3RpY2UgaG93IHdlIG5hbWVkIHRoZSBvdXRwdXQgb2YgYHJlY2lwZSgpYC4gDQpUaGUgbmFtaW5nIGNvbnZlbnRpb24gZm9yIHJlY2lwZSBvYmplY3RzIGlzIGAqX3JlY2Agb3IgYHJlY2AuIA0KDQpOb3csIGxldCdzIGdldCBiYWNrIHRvIHRoZSBgaWRgIHZhcmlhYmxlLiANCkluc3RlYWQgb2YgaW5jbHVkaW5nIGl0IGFzIGEgcHJlZGljdG9yIHZhcmlhYmxlLCB3ZSBjb3VsZCBhbHNvIHVzZSB0aGUgYHVwZGF0ZV9yb2xlKClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVjaXBlc2AgcGFja2FnZS4NCg0KYGBge3J9DQpzaW1wbGVfcmVjIDwtIHRyYWluX3BtICU+JQ0KICByZWNpcGVzOjpyZWNpcGUodmFsdWUgfiAuKSAlPiUNCiAgcmVjaXBlczo6dXBkYXRlX3JvbGUoaWQsIG5ld19yb2xlID0gImlkIHZhcmlhYmxlIikNCg0Kc2ltcGxlX3JlYw0KYGBgDQoNCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayBoZXJlIGxlYXJuIG1vcmUgYWJvdXQgdGhlIHdvcmtpbmcgd2l0aCBgaWRgIHZhcmlhYmxlcyA8L3N1bW1hcnk+DQoNClRoaXMgb3B0aW9uIHdvcmtzIHdlbGwgd2l0aCB0aGUgbmV3ZXIgYHdvcmtmbG93c2AgcGFja2FnZSwgaG93ZXZlciBgaWRgIHZhcmlhYmxlcyBhcmUgb2Z0ZW4gZHJvcHBlZCBmcm9tIGFuYWx5c2VzIHRoYXQgZG8gbm90IHVzZSB0aGlzIG5ld2VyIHBhY2thZ2UgYXMgdGhleSBjYW4gbWFrZSB0aGUgcHJvY2VzcyBkaWZmaWN1bHQgd2l0aCB1c2luZyB0aGUgYHBhcnNuaXBgIHBhY2thZ2UgYWxvbmUgZHVlIHRvIHRoZSBmYWN0IHRoYXQgbmV3IGxldmVscyAob3IgcG9zc2libGUgdmFsdWVzKSBtYXkgYmUgaW50cm9kdWNlZCB3aXRoIHRoZSB0ZXN0aW5nIGRhdGEuDQoNCjwvZGV0YWlscz4NCg0KV2UgY291bGQgYWxzbyBzcGVjaWZ5IHRoZSBvdXRjb21lIGFuZCBwcmVkaWN0b3JzIGluIHRoZSBzYW1lIHdheSBhcyB3ZSBqdXN0IHNwZWNpZmllZCB0aGUgaWQgdmFyaWFibGUuIA0KUGxlYXNlIHNlZSBbaGVyZV0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzL3JlZmVyZW5jZS9yZWNpcGUuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgZXhhbXBsZXMgb2Ygb3RoZXIgcm9sZXMgZm9yIHZhcmlhYmxlcy4gDQpUaGUgcm9sZSBjYW4gYmUgYWN0dWFsbHkgYmUgYW55IHZhbHVlLiANCg0KVGhlIG9yZGVyIGlzIGltcG9ydGFudCBoZXJlLCBhcyB3ZSBmaXJzdCBtYWtlIGFsbCB2YXJpYWJsZXMgcHJlZGljdG9ycyBhbmQgdGhlbiBvdmVycmlkZSB0aGlzIHJvbGUgZm9yIHRoZSBvdXRjb21lIGFuZCBgaWRgIHZhcmlhYmxlLiANCldlIHdpbGwgdXNlIHRoZSBgZXZlcnl0aGluZygpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIHRvIHN0YXJ0IHdpdGggYWxsIG9mIHRoZSB2YXJpYWJsZXMgaW4gYHRyYWluX3BtYC4NCg0KYGBge3J9DQpzaW1wbGVfcmVjIDwtcmVjaXBlKHRyYWluX3BtKSAlPiUNCiAgICB1cGRhdGVfcm9sZShldmVyeXRoaW5nKCksIG5ld19yb2xlID0gInByZWRpY3RvciIpJT4lDQogICAgdXBkYXRlX3JvbGUodmFsdWUsIG5ld19yb2xlID0gIm91dGNvbWUiKSU+JQ0KICAgIHVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpDQoNCnNpbXBsZV9yZWMNCmBgYA0KDQpXZSBjYW4gdmlldyBvdXIgcmVjaXBlIGluIG1vcmUgZGV0YWlsIHVzaW5nIHRoZSBiYXNlIGBzdW1tYXJ5KClgIGZ1bmN0aW9uLg0KDQpgYGB7cn0NCnN1bW1hcnkoc2ltcGxlX3JlYykNCmBgYA0KDQpUbyBzdW1tYXJpemUgdGhpcyBzdGVwLCB3ZSB1c2UgdGhlIGByZWNpcGUoKWAgZnVuY3Rpb24gdG8gYXNzaWduIHJvbGVzIHRvIGFsbCB0aGUgdmFyaWFibGVzOiANCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNDAwcHgifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiU3RhcnRpbmdfYV9yZWNpcGVfcmVjaXBlczEucG5nIikpDQpgYGANCg0KDQojIyMgU3RlcCAyOiBTcGVjaWZ5IHRoZSBwcmUtcHJvY2Vzc2luZyBzdGVwcyB3aXRoIGBzdGVwKigpYCBmdW5jdGlvbnMNCg0KTmV4dCwgd2UgdXNlIHRoZSBgc3RlcCooKWAgZnVuY3Rpb25zIGZyb20gdGhlIGByZWNpcGVgIHBhY2thZ2UgdG8gc3BlY2lmeSBwcmUtcHJvY2Vzc2luZyBzdGVwcy4gDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIk1ha2luZ19hX3JlY2lwZV9yZWNpcGVzMi5wbmciKSkNCmBgYA0KDQoqKlRoaXMgW2xpbmtdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy9yZWZlcmVuY2UvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBhbmQgdGhpcyBbbGlua10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JlY2lwZXMvcmVjaXBlcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gc2hvdyB0aGUgbWFueSBvcHRpb25zIGZvciByZWNpcGUgc3RlcCBmdW5jdGlvbnMuKioNCg0KPHU+VGhlcmUgYXJlIHN0ZXAgZnVuY3Rpb25zIGZvciBhIHZhcmlldHkgb2YgcHVycG9zZXM6PC91Pg0KDQoxLiBbKipJbXB1dGF0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0ltcHV0YXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIGZpbGxpbmcgaW4gbWlzc2luZyB2YWx1ZXMgYmFzZWQgb24gdGhlIGV4aXN0aW5nIGRhdGEgDQoyLiBbKipUcmFuc2Zvcm1hdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EYXRhX3RyYW5zZm9ybWF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAtLSBjaGFuZ2luZyBhbGwgdmFsdWVzIG9mIGEgdmFyaWFibGUgaW4gdGhlIHNhbWUgd2F5LCB0eXBpY2FsbHkgdG8gbWFrZSBpdCBtb3JlIG5vcm1hbCBvciBlYXNpZXIgdG8gaW50ZXJwcmV0DQozLiBbKipEaXNjcmV0aXphdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaXNjcmV0aXphdGlvbl9vZl9jb250aW51b3VzX2ZlYXR1cmVzKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIGNvbnZlcnRpbmcgY29udGludW91cyB2YWx1ZXMgaW50byBkaXNjcmV0ZSBvciBub21pbmFsIHZhbHVlcyAtIGJpbm5pbmcgZm9yIGV4YW1wbGUgdG8gcmVkdWNlIHRoZSBudW1iZXIgb2YgcG9zc2libGUgbGV2ZWxzIChIb3dldmVyIHRoaXMgaXMgZ2VuZXJhbGx5IG5vdCBhZHZpc2FibGUhKQ0KNC4gWyoqRW5jb2RpbmcgLyBDcmVhdGluZyBEdW1teSBWYXJpYWJsZXMqKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRHVtbXlfdmFyaWFibGVfKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIGNyZWF0aW5nIGEgbnVtZXJpYyBjb2RlIGZvciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMNCihbKipNb3JlIG9uIER1bW15IFZhcmlhYmxlcyBhbmQgb25lLWhvdCBlbmNvZGluZyoqXShodHRwczovL21lZGl1bS5jb20vcC9iNTg0MGJlM2M0MWEvcmVzcG9uc2VzL3Nob3cpe3RhcmdldD0iX2JsYW5rIn0pDQo1LiBbKipEYXRhIHR5cGUgY29udmVyc2lvbnMqKl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2hhYmxhci92aWduZXR0ZXMvY29udmVydC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAtLSB3aGljaCBtZWFucyBjaGFuZ2luZyBmcm9tIGludGVnZXIgdG8gZmFjdG9yIG9yIG51bWVyaWMgdG8gZGF0ZSBldGMuDQo2LiBbKipJbnRlcmFjdGlvbioqXShodHRwczovL3N0YXRpc3RpY3NieWppbS5jb20vcmVncmVzc2lvbi9pbnRlcmFjdGlvbi1lZmZlY3RzLyl7dGFyZ2V0PSJfYmxhbmsifSAgdGVybSBhZGRpdGlvbiB0byB0aGUgbW9kZWwgLS0gd2hpY2ggbWVhbnMgdGhhdCB3ZSB3b3VsZCBiZSBtb2RlbGluZyBmb3IgcHJlZGljdG9ycyB0aGF0IHdvdWxkIGluZmx1ZW5jZSB0aGUgY2FwYWNpdHkgb2YgZWFjaCBvdGhlciB0byBwcmVkaWN0IHRoZSBvdXRjb21lDQo3LiBbKipOb3JtYWxpemF0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL05vcm1hbGl6YXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIGNlbnRlcmluZyBhbmQgc2NhbGluZyB0aGUgZGF0YSB0byBhIHNpbWlsYXIgcmFuZ2Ugb2YgdmFsdWVzDQo4LiBbKipEaW1lbnNpb25hbGl0eSBSZWR1Y3Rpb24vIFNpZ25hbCBFeHRyYWN0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RpbWVuc2lvbmFsaXR5X3JlZHVjdGlvbil7dGFyZ2V0PSJfYmxhbmsifSAtLSByZWR1Y2luZyB0aGUgc3BhY2Ugb2YgZmVhdHVyZXMgb3IgcHJlZGljdG9ycyB0byBhIHNtYWxsZXIgc2V0IG9mIHZhcmlhYmxlcyB0aGF0IGNhcHR1cmUgdGhlIHZhcmlhdGlvbiBvciBzaWduYWwgaW4gdGhlIG9yaWdpbmFsIHZhcmlhYmxlcyAoZXguIFByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXMgYW5kIEluZGVwZW5kZW50IENvbXBvbmVudCBBbmFseXNpcykNCjkuICoqRmlsdGVyaW5nKiogLS0gZmlsdGVyaW5nIG9wdGlvbnMgZm9yIHJlbW92aW5nIHZhcmlhYmxlcyAoZXguIHJlbW92ZSB2YXJpYWJsZXMgdGhhdCBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgdG8gb3RoZXJzIG9yIHJlbW92ZSB2YXJpYWJsZXMgd2l0aCB2ZXJ5IGxpdHRsZSB2YXJpYW5jZSBhbmQgdGhlcmVmb3JlIGxpa2VseSBsaXR0bGUgcHJlZGljdGl2ZSBjYXBhY2l0eSkNCjEwLiBbKipSb3cgb3BlcmF0aW9ucyoqXShodHRwczovL3RhcnRhcnVzLm9yZy9nYXJldGgvbWF0aHMvTGluZWFyX0FsZ2VicmEvcm93X29wZXJhdGlvbnMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIHBlcmZvcm1pbmcgZnVuY3Rpb25zIG9uIHRoZSB2YWx1ZXMgd2l0aGluIHRoZSByb3dzICAoZXguIHJlYXJyYW5naW5nLCBmaWx0ZXJpbmcsIGltcHV0aW5nKQ0KMTEuICoqQ2hlY2tpbmcgZnVuY3Rpb25zKiogLS0gU2FuaXR5IGNoZWNrcyB0byBsb29rIGZvciBtaXNzaW5nIHZhbHVlcywgdG8gbG9vayBhdCB0aGUgdmFyaWFibGUgY2xhc3NlcyBldGMuDQoNCkFsbCBvZiB0aGUgc3RlcCBmdW5jdGlvbnMgbG9vayBsaWtlIGBzdGVwXyooKWAgd2l0aCB0aGUgYCpgIHJlcGxhY2VkIHdpdGggYSBuYW1lLCBleGNlcHQgZm9yIHRoZSBjaGVjayBmdW5jdGlvbnMgd2hpY2ggbG9vayBsaWtlIGBjaGVja18qKClgLg0KDQpUaGVyZSBhcmUgc2V2ZXJhbCB3YXlzIHRvIHNlbGVjdCB3aGF0IHZhcmlhYmxlcyB0byBhcHBseSBzdGVwcyB0bzogIA0KDQoxLiBVc2luZyBgdGlkeXNlbGVjdGAgbWV0aG9kczogYGNvbnRhaW5zKClgLCBgbWF0Y2hlcygpYCwgYHN0YXJ0c193aXRoKClgLCBgZW5kc193aXRoKClgLCBgZXZlcnl0aGluZygpYCwgYG51bV9yYW5nZSgpYCAgDQoyLiBVc2luZyB0aGUgdHlwZTogYGFsbF9ub21pbmFsKClgLCBgYWxsX251bWVyaWMoKWAgLCBgaGFzX3R5cGUoKWAgDQozLiBVc2luZyB0aGUgcm9sZTogYGFsbF9wcmVkaWN0b3JzKClgLCBgYWxsX291dGNvbWVzKClgLCBgaGFzX3JvbGUoKWANCjQuIFVzaW5nIHRoZSBuYW1lIC0gdXNlIHRoZSBhY3R1YWwgbmFtZSBvZiB0aGUgdmFyaWFibGUvdmFyaWFibGVzIG9mIGludGVyZXN0ICANCg0KTGV0J3MgdHJ5IGFkZGluZyBzb21lIHN0ZXBzIHRvIG91ciByZWNpcGUuDQoNCg0KV2UgbWlnaHQgd2FudCB0byBwb3RlbnRpYWxseSBbb25lLWhvdCBlbmNvZGVdKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vd2h5LW9uZS1ob3QtZW5jb2RlLWRhdGEtaW4tbWFjaGluZS1sZWFybmluZy8pe3RhcmdldD0iX2JsYW5rIn0gc29tZSBvZiBvdXIgY2F0ZWdvcmljYWwgdmFyaWFibGVzIHNvIHRoYXQgdGhleSBjYW4gYmUgdXNlZCB3aXRoIGNlcnRhaW4gYWxnb3JpdGhtcy4gDQoNCldlIGNhbiBkbyB0aGlzIHdpdGggdGhlIGBzdGVwX2R1bW15KClgIGZ1bmN0aW9uIGFuZCB0aGUgYG9uZV9ob3QgPSBUUlVFYCBhcmd1bWVudC4gDQpPbmUtaG90IGVuY29kaW5nIG1lYW5zIHRoYXQgd2UgZG8gbm90IHNpbXBseSBlbmNvZGUgb3VyIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBudW1lcmljYWxseSwgYXMgb3VyIG51bWVyaWMgYXNzaWdubWVudHMgY2FuIGJlIGludGVycHJldGVkIGJ5IGFsZ29yaXRobXMgYXMgaGF2aW5nIGEgcGFydGljdWxhciByYW5rIG9yIG9yZGVyLiANCkluc3RlYWQsIGJpbmFyeSB2YXJpYWJsZXMgbWFkZSBvZiAxcyBhbmQgMHMgYXJlIHVzZWQgdG8gYXJiaXRyYXJpbHkgYXNzaWduIGEgbnVtZXJpYyB2YWx1ZSB0aGF0IGhhcyBubyBhcHBhcmVudCBvcmRlci4NCg0KYGBge3J9DQpzaW1wbGVfcmVjICU+JQ0KICBzdGVwX2R1bW15KHN0YXRlLCBjb3VudHksIGNpdHksIHpjdGEsIG9uZV9ob3QgPSBUUlVFKQ0KYGBgDQoNCk91ciBgZmlwc2AgdmFyaWFibGUgaW5jbHVkZXMgYSBudW1lcmljIGNvZGUgZm9yIHN0YXRlIGFuZCBjb3VudHkgLSBhbmQgdGhlcmVmb3JlIGlzIGVzc2VudGlhbGx5IGEgcHJveHkgZm9yIGNvdW50eS4NClNpbmNlIHdlIGFscmVhZHkgaGF2ZSBjb3VudHksIHdlIHdpbGwganVzdCB1c2UgaXQgYW5kIGtlZXAgdGhlIGBmaXBzYCBJRCBhcyBhbm90aGVyIElEIHZhcmlhYmxlLg0KDQpXZSBjYW4gcmVtb3ZlIHRoZSBgZmlwc2AgdmFyaWFibGUgZnJvbSB0aGUgcHJlZGljdG9ycyB1c2luZyBgdXBkYXRlX3JvbGUoKWAgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIHJvbGUgaXMgbm8gbG9uZ2VyIGAicHJlZGljdG9yImAuIA0KV2UgY2FuIG1ha2UgdGhlIHJvbGUgYW55dGhpbmcgd2Ugd2FudCBhY3R1YWxseSwgc28gd2Ugd2lsbCBrZWVwIGl0IHNvbWV0aGluZyBpZGVudGlmaWFibGUuDQoNCmBgYHtyfQ0Kc2ltcGxlX3JlYyAlPiUNCiAgdXBkYXRlX3JvbGUoImZpcHMiLCBuZXdfcm9sZSA9ICJjb3VudHkgaWQiKQ0KYGBgDQoNCldlIG1pZ2h0IGFsc28gd2FudCB0byByZW1vdmUgdmFyaWFibGVzIHRoYXQgYXBwZWFyIHRvIGJlIHJlZHVuZGFudCBhbmQgYXJlIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggb3RoZXJzLCBhcyB3ZSBrbm93IGZyb20gb3VyIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgdGhhdCBtYW55IG9mIG91ciB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlci4gDQpXZSBjYW4gZG8gdGhpcyB1c2luZyB0aGUgYHN0ZXBfY29ycigpYCBmdW5jdGlvbi4NCg0KV2UgZG9uJ3Qgd2FudCB0byByZW1vdmUgc29tZSBvZiBvdXIgdmFyaWFibGVzLCBsaWtlIHRoZSBgQ01BUWAgYW5kIGBhb2RgIHZhcmlhYmxlcywgd2UgY2FuIHNwZWNpZnkgdGhpcyB1c2luZyB0aGUgYC1gIHNpZ24gYmVmb3JlIHRoZSBuYW1lcyBvZiB0aGVzZSB2YXJpYWJsZXMgbGlrZSBzbzoNCg0KYGBge3J9DQpzaW1wbGVfcmVjICU+JQ0KICBzdGVwX2NvcnIoYWxsX3ByZWRpY3RvcnMoKSwgLSBDTUFRLCAtIGFvZCkNCmBgYA0KDQoNCkl0IGlzIGFsc28gYSBnb29kIGlkZWEgdG8gcmVtb3ZlIHZhcmlhYmxlcyB3aXRoIG5lYXItemVybyB2YXJpYW5jZSwgd2hpY2ggY2FuIGJlIGRvbmUgd2l0aCB0aGUgYHN0ZXBfbnp2KClgIGZ1bmN0aW9uLiANCg0KVmFyaWFibGVzIGhhdmUgbG93IHZhcmlhbmNlIGlmIGFsbCB0aGUgdmFsdWVzIGFyZSB2ZXJ5IHNpbWlsYXIsIHRoZSB2YWx1ZXMgYXJlIHZlcnkgc3BhcnNlLCBvciBpZiB0aGV5IGFyZSBoaWdobHkgaW1iYWxhbmNlZC4gQWdhaW4gd2UgZG9uJ3Qgd2FudCB0byByZW1vdmUgb3VyIGBDTUFRYCBhbmQgYGFvZGAgdmFyaWFibGVzLg0KDQpgYGB7cn0NCnNpbXBsZV9yZWMgJT4lDQogIHN0ZXBfbnp2KGFsbF9wcmVkaWN0b3JzKCksIC0gQ01BUSwgLSBhb2QpDQpgYGANCg0KPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gbGVhcm4gYWJvdXQgZXhhbXBsZXMgd2hlcmUgeW91IG1pZ2h0IGhhdmUgbmVhci16ZXJvIHZhcmlhbmNlIHZhcmlhYmxlczwvc3VtbWFyeT4NCg0KMSkgKipTaW1pbGFyIFZhbHVlcyoqIC0gSWYgdGhlIHBvcHVsYXRpb24gZGVuc2l0eSB3YXMgbmVhcmx5IHRoZSBzYW1lIGZvciBldmVyeSB6Y3RhIHRoYXQgY29udGFpbmVkIGEgbW9uaXRvciwgdGhlbiBrbm93aW5nIHRoZSBwb3B1bGF0aW9uIGRlbnNpdHkgbmVhciBvdXIgbW9uaXRvciB3b3VsZCBjb250cmlidXRlIGxpdHRsZSB0byBvdXIgbW9kZWwgaW4gYXNzaXN0aW5nIHVzIHRvIHByZWRpY3QgbW9uaXRvciBhaXIgcG9sbHV0aW9uIHZhbHVlcy4gDQoyKSAqKlNwYXJzZSBEYXRhKiogLSBJZiBhbGwgb2YgdGhlIG1vbml0b3JzIHdlcmUgaW4gbG9jYXRpb25zIHdoZXJlIHRoZSBwb3B1bGF0aW9ucyBkaWQgbm90IGF0dGVuZCBncmFkdWF0ZSBzY2hvb2wsIHRoZW4gdGhlc2UgdmFsdWVzIHdvdWxkIG1vc3RseSBiZSB6ZXJvLCBhZ2FpbiB0aGlzIHdvdWxkIGRvIHZlcnkgbGl0dGxlIHRvIGhlbHAgdXMgZGlzdGluZ3Vpc2ggb3VyIGFpciBwb2xsdXRpb24gbW9uaXRvcnMuV2hlbiBtYW55IG9mIHRoZSB2YWx1ZXMgYXJlIHplcm8gdGhpcyBpcyBhbHNvIGNhbGxlZCBzcGFyc2UgZGF0YS4gIA0KMykgKipJbWJhbGFuY2VkIERhdGEqKiBJZiBuZWFybHkgYWxsIG9mIHRoZSBtb25pdG9ycyB3ZXJlIGxvY2F0ZWQgaW4gb25lIHBhcnRpY3VsYXIgc3RhdGUsIGFuZCBhbGwgdGhlIG90aGVycyBvbmx5IGhhZCBvbmUgbW9uaXRvciBlYWNoLCB0aGVuIHRoZSByZWFsIHByZWRpY3RpdmUgdmFsdWUgd291bGQgc2ltcGx5IGJlIGluIGtub3dpbmcgaWYgYSBtb25pdG9yIGlzIGxvY2F0ZWQgaW4gdGhhdCBwYXJ0aWN1bGFyIHN0YXRlIG9yIG5vdC4gSW4gdGhpcyBjYXNlIHdlIGRvbid0IHdhbnQgdG8gcmVtb3ZlIG91ciB2YXJpYWJsZSwgd2UganVzdCB3YW50IHRvIHNpbXBsaWZ5IGl0Lg0KDQpTZWUgdGhpcyBbYmxvZyBwb3N0XShodHRwczovL3d3dy5yLWJsb2dnZXJzLmNvbS9uZWFyLXplcm8tdmFyaWFuY2UtcHJlZGljdG9ycy1zaG91bGQtd2UtcmVtb3ZlLXRoZW0vKXt0YXJnZXQ9Il9ibGFuayJ9IGFib3V0IHdoeSByZW1vdmluZyBuZWFyLXplcm8gdmFyaWFuY2UgdmFyaWFibGVzIGlzbid0IGFsd2F5cyBhIGdvb2QgaWRlYSBpZiB3ZSB0aGluayB0aGF0IGEgdmFyaWFibGUgbWlnaHQgYmUgZXNwZWNpYWxseSBpbmZvcm1hdGl2ZS4NCg0KPC9kZXRhaWxzPg0KDQpMZXQncyBwdXQgYWxsIHRoaXMgdG9nZXRoZXIgbm93LiANCg0KKipSZW1lbWJlcjogaXQgaXMgaW1wb3J0YW50IHRvIGFkZCB0aGUgc3RlcHMgdG8gdGhlIHJlY2lwZSBpbiBhbiBvcmRlciB0aGF0IG1ha2VzIHNlbnNlIGp1c3QgbGlrZSB3aXRoIGEgY29va2luZyByZWNpcGUuKioNCg0KRmlyc3QsIHdlIGFyZSBnb2luZyB0byBjcmVhdGUgbnVtZXJpYyB2YWx1ZXMgZm9yIG91ciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMsIHRoZW4gd2Ugd2lsbCBsb29rIGF0IGNvcnJlbGF0aW9uIGFuZCBuZWFyLXplcm8gdmFyaWFuY2UuIA0KQWdhaW4sIHdlIGRvIG5vdCB3YW50IHRvIHJlbW92ZSB0aGUgYENNQVFgIGFuZCBgYW9kYCB2YXJpYWJsZXMsIHNvIHdlIGNhbiBtYWtlIHN1cmUgdGhleSBhcmUga2VwdCBpbiB0aGUgbW9kZWwgYnkgZXhjbHVkaW5nIHRoZW0gZnJvbSB0aG9zZSBzdGVwcy4gDQpJZiB3ZSBzcGVjaWZpY2FsbHkgd2FudGVkIHRvIHJlbW92ZSBhIHByZWRpY3RvciB3ZSBjb3VsZCB1c2UgYHN0ZXBfcm0oKWAuDQoNCmBgYHtyfQ0Kc2ltcGxlX3JlYyAlPD4lDQogIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikgJT4lDQogIHN0ZXBfZHVtbXkoc3RhdGUsIGNvdW50eSwgY2l0eSwgemN0YSwgb25lX2hvdCA9IFRSVUUpICU+JQ0KICBzdGVwX2NvcnIoYWxsX3ByZWRpY3RvcnMoKSwgLSBDTUFRLCAtIGFvZCklPiUNCiAgc3RlcF9uenYoYWxsX3ByZWRpY3RvcnMoKSwgLSBDTUFRLCAtIGFvZCkNCiAgDQpzaW1wbGVfcmVjDQpgYGANCg0KDQoNCiMjICoqUnVubmluZyB0aGUgcHJlLXByb2Nlc3NpbmcqKg0KKioqDQoNCiMjIyAqKlN0ZXAgMTogVXBkYXRlIHRoZSByZWNpcGUgd2l0aCB0cmFpbmluZyBkYXRhIHVzaW5nIGBwcmVwKClgKioNCioqKg0KDQpUaGUgbmV4dCBtYWpvciBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UgaXMgYHByZXAoKWAuDQpUaGlzIGZ1bmN0aW9uIHVwZGF0ZXMgdGhlIHJlY2lwZSBvYmplY3QgYmFzZWQgb24gdGhlIHRyYWluaW5nIGRhdGEuIA0KSXQgZXN0aW1hdGVzIHBhcmFtZXRlcnMgKGVzdGltYXRpbmcgdGhlIHJlcXVpcmVkIHF1YW50aXRpZXMgYW5kIHN0YXRpc3RpY3MgcmVxdWlyZWQgYnkgdGhlIHN0ZXBzIGZvciB0aGUgdmFyaWFibGVzKSBmb3IgcHJlLXByb2Nlc3NpbmcgYW5kIHVwZGF0ZXMgdGhlIHZhcmlhYmxlcyByb2xlcywgYXMgc29tZSBvZiB0aGUgcHJlZGljdG9ycyBtYXkgYmUgcmVtb3ZlZCwgdGhpcyBhbGxvd3MgdGhlIHJlY2lwZSB0byBiZSByZWFkeSB0byB1c2Ugb24gb3RoZXIgZGF0YSBzZXRzLiANCkl0ICoqZG9lcyBub3QgbmVjZXNzYXJpbHkgYWN0dWFsbHkgZXhlY3V0ZSB0aGUgcHJlLXByb2Nlc3NpbmcgaXRzZWxmKiosIGhvd2V2ZXIgd2Ugd2lsbCBzcGVjaWZ5IGluIGFyZ3VtZW50IGZvciBpdCB0byBkbyB0aGlzIHNvIHRoYXQgd2UgY2FuIHRha2UgYSBsb29rIGF0IHRoZSBwcmUtcHJvY2Vzc2VkIGRhdGEuDQoNCg0KVGhlcmUgYXJlIHNvbWUgaW1wb3J0YW50IGFyZ3VtZW50cyB0byBrbm93IGFib3V0Og0KDQoxLiBgdHJhaW5pbmdgIC0geW91IG11c3Qgc3VwcGx5IGEgdHJhaW5pbmcgZGF0YSBzZXQgdG8gZXN0aW1hdGUgcGFyYW1ldGVycyBmb3IgcHJlLXByb2Nlc3Npbmcgb3BlcmF0aW9ucyAocmVjaXBlIHN0ZXBzKSAtIHRoaXMgbWF5IGFscmVhZHkgYmUgaW5jbHVkZWQgaW4geW91ciByZWNpcGUgLSBhcyBpcyB0aGUgY2FzZSBmb3IgdXMNCjIuIGBmcmVzaGAgLSBpZiBgZnJlc2g9VFJVRWAsIC0gd2lsbCByZXRyYWluIGFuZCBlc3RpbWF0ZSBwYXJhbWV0ZXJzIGZvciBhbnkgcHJldmlvdXMgc3RlcHMgdGhhdCB3ZXJlIGFscmVhZHkgcHJlcHBlZCBpZiB5b3UgYWRkIG1vcmUgc3RlcHMgdG8gdGhlIHJlY2lwZQ0KMy4gYHZlcmJvc2VgIC0gaWYgYHZlcmJvc2U9VFJVRWAsIHNob3dzIHRoZSBwcm9ncmVzcyBhcyB0aGUgc3RlcHMgYXJlIGV2YWx1YXRlZCBhbmQgdGhlIHNpemUgb2YgdGhlIHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgc2V0DQo0LiBgcmV0YWluYCAtIGlmIGByZXRhaW49VFJVRWAsIHRoZW4gdGhlIHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgc2V0IHdpbGwgYmUgc2F2ZWQgd2l0aGluIHRoZSByZWNpcGUgKGFzIHRlbXBsYXRlKS4gVGhpcyBpcyBnb29kIGlmIHlvdSBhcmUgbGlrZWx5IHRvIGFkZCBtb3JlIHN0ZXBzIGFuZCBkbyBub3Qgd2FudCB0byByZXJ1biB0aGUgYHByZXAoKWAgb24gdGhlIHByZXZpb3VzIHN0ZXBzLiBIb3dldmVyIHRoaXMgY2FuIG1ha2UgdGhlIHJlY2lwZSBzaXplIGxhcmdlLiBUaGlzIGlzIG5lY2Vzc2FyeSBpZiB5b3Ugd2FudCB0byBhY3R1YWxseSBsb29rIGF0IHRoZSBwcmUtcHJvY2Vzc2VkIGRhdGEuDQoNCkxldCdzIHRyeSBvdXQgdGhlIGBwcmVwKClgIGZ1bmN0aW9uOiANCg0KYGBge3J9DQpwcmVwcGVkX3JlYyA8LSBwcmVwKHNpbXBsZV9yZWMsIHZlcmJvc2UgPSBUUlVFLCByZXRhaW4gPSBUUlVFICkNCm5hbWVzKHByZXBwZWRfcmVjKQ0KYGBgDQoNClRoZXJlIGFyZSBhbHNvIGxvdHMgb2YgdXNlZnVsIHRoaW5ncyB0byBjaGVja291dCBpbiB0aGUgb3V0cHV0IG9mIGBwcmVwKClgLg0KWW91IGNhbiBzZWU6DQoNCjEuIHRoZSBgc3RlcHNgIHRoYXQgd2VyZSBydW4gIA0KMi4gdGhlIG9yaWdpbmFsIHZhcmlhYmxlIGluZm8gKGB2YXJfaW5mb2ApICANCjMuIHRoZSB1cGRhdGVkIHZhcmlhYmxlIGluZm8gYWZ0ZXIgcHJlLXByb2Nlc3NpbmcgKGB0ZXJtX2luZm9gKQ0KNC4gdGhlIG5ldyBgbGV2ZWxzYCBvZiB0aGUgdmFyaWFibGVzIA0KNS4gdGhlIG9yaWdpbmFsIGxldmVscyBvZiB0aGUgdmFyaWFibGVzIChgb3JpZ19sdmxzYCkNCjYuIGluZm8gYWJvdXQgdGhlIHRyYWluaW5nIGRhdGEgc2V0IHNpemUgYW5kIGNvbXBsZXRlbmVzcyAoYHRyX2luZm9gKQ0KDQoqKk5vdGUqKjogWW91IG1heSBzZWUgdGhlIGBwcmVwLnJlY2lwZSgpYCBmdW5jdGlvbiBpbiBtYXRlcmlhbCB0aGF0IHlvdSByZWFkIGFib3V0IHRoZSBgcmVjaXBlc2AgcGFja2FnZS4gVGhpcyBpcyByZWZlcnJpbmcgdG8gdGhlIGBwcmVwKClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVjaXBlc2AgcGFja2FnZS4NCg0KDQojIyMgKipTdGVwIDI6IEV4dHJhY3QgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIHVzaW5nIGBiYWtlKClgKioNCioqKg0KDQoNClNpbmNlIHdlIHJldGFpbmVkIG91ciBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgKGkuZS4gYHByZXAocmV0YWluPVRSVUUpYCksIHdlIGNhbiB0YWtlIGEgbG9vayBhdCBpdCBieSB1c2luZyB0aGUgYGJha2UoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlIGxpa2UgdGhpczoNCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNDAwcHgifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwidHJhaW5pbmdfcHJlcHJvY2Vzc2luZ19yZWNpcGVzMy5wbmciKSkNCmBgYA0KDQpMZXQncyBiYWtlISANCg0KU2luY2Ugd2UgZG9uJ3QgaGF2ZSBuZXcgZGF0YSAod2UgYXJlbid0IGxvb2tpbmcgYXQgdGhlIHRlc3RpbmcgZGF0YSksIHdlIG5lZWQgdG8gc3BlY2lmeSB0aGlzIHdpdGggYG5ld19kYXRhID0gTlVMTGAuDQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCmBgYHtyfQ0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQ0KYmFrZWRfdHJhaW4gPC0gYmFrZShwcmVwcGVkX3JlYywgbmV3X2RhdGEgPSBOVUxMKQ0KZ2xpbXBzZShiYWtlZF90cmFpbikNCmBgYA0KIyMjIw0KDQoqKk5vdGUqKi0gdGhpcyBwcm9jZXNzIHVzZWQgdG8gcmVxdWlyZSB0aGUgYGp1aWNlKClgIGZ1bmN0aW9uLg0KDQpGb3IgZWFzeSBjb21wYXJpc29uIHNha2UgLSBoZXJlIGlzIG91ciBvcmlnaW5hbCBkYXRhOg0KDQojIyMjIHsuc2Nyb2xsYWJsZSB9DQoNCmBgYHtyfQ0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQ0KZ2xpbXBzZShwbSkNCmBgYA0KIyMjIw0KDQpOb3RpY2UgaG93IHdlIG9ubHkgaGF2ZSAzNiB2YXJpYWJsZXMgbm93IGluc3RlYWQgb2YgNTAhIA0KVHdvIG9mIHRoZXNlIGFyZSBvdXIgSUQgdmFyaWFibGVzIChgZmlwc2AgYW5kIHRoZSBhY3R1YWwgbW9uaXRvciBJRCAoYGlkYCkpIGFuZCBvbmUgaXMgb3VyIG91dGNvbWUgKGB2YWx1ZWApLiANClRodXMgd2Ugb25seSBoYXZlIDMzIHByZWRpY3RvcnMgbm93LiANCldlIGNhbiBhbHNvIHNlZSB0aGF0IHdlIG5vIGxvbmdlciBoYXZlIGFueSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuIA0KVmFyaWFibGVzIGxpa2UgYHN0YXRlYCBhcmUgZ29uZSBhbmQgb25seSBgc3RhdGVfQ2FsaWZvcm5pYWAgcmVtYWlucyBhcyBpdCB3YXMgdGhlIG9ubHkgc3RhdGUgaWRlbnRpdHkgdG8gaGF2ZSBub256ZXJvIHZhcmlhbmNlLg0KV2UgY2FuIGFsc28gc2VlIHRoYXQgdGhlcmUgd2VyZSBtb3JlIG1vbml0b3JzIGxpc3RlZCBhcyBgIk5vdCBpbiBhIGNpdHkiYCB0aGFuIGFueSBjaXR5LiANCg0KV2UgY2FuIHNlZSB0aGF0IENhbGlmb3JuaWEgaGFkIHRoZSBsYXJnZXN0IG51bWJlciBvZiBtb25pdG9ycyBjb21wYXJlZCB0byB0aGUgb3RoZXIgc3RhdGVzLg0KDQpgYGB7ciwgZXZhbCA9IEZBTFNFfQ0KcG0gJT4lIGNvdW50KHN0YXRlKSANCmBgYA0KDQoNClNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQ6DQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCnBtICU+JSBjb3VudChzdGF0ZSkgICU+JQ0KICBwcmludChuID0gMWUzKQ0KYGBgDQoNCiMjIyMNCg0KYGBge3IsIGV2YWwgPSBGQUxTRX0NCnBtICU+JSBjb3VudChjaXR5KQ0KYGBgDQoNClNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQ6DQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCg0KYGBge3IsIGVjaG89RkFMU0V9DQpwbSAlPiUgY291bnQoY2l0eSkgJT4lDQogIHByaW50KG4gPSAxZTMpDQpgYGANCg0KIyMjIw0KDQoqKk5vdGUqKjogUmVjYWxsIHRoYXQgeW91IG11c3Qgc3BlY2lmeSBgcmV0YWluID0gVFJVRWAgYXJndW1lbnQgb2YgdGhlIGBwcmVwKClgIGZ1bmN0aW9uIHRvIHVzZSBgYmFrZSgpYC4NCg0KIyMjICoqU3RlcCAzOiBFeHRyYWN0IHByZS1wcm9jZXNzZWQgdGVzdGluZyBkYXRhIHVzaW5nIGBiYWtlKClgKioNCioqKg0KDQpBY2NvcmRpbmcgdG8gdGhlIGB0aWR5bW9kZWxzYCBkb2N1bWVudGF0aW9uOg0KDQo+IGBiYWtlKClgIHRha2VzIGEgdHJhaW5lZCByZWNpcGUgYW5kIGFwcGxpZXMgdGhlIG9wZXJhdGlvbnMgdG8gYSBkYXRhIHNldCB0byBjcmVhdGUgYSBkZXNpZ24gbWF0cml4Lg0KIEZvciBleGFtcGxlOiBpdCBhcHBsaWVzIHRoZSBjZW50ZXJpbmcgdG8gbmV3IGRhdGEgc2V0cyB1c2luZyB0aGVzZSBtZWFucyB1c2VkIHRvIGNyZWF0ZSB0aGUgcmVjaXBlLg0KDQpUaGVyZWZvcmUsIGlmIHlvdSB3YW50ZWQgdG8gbG9vayBhdCB0aGUgcHJlLXByb2Nlc3NlZCB0ZXN0aW5nIGRhdGEgeW91IHdvdWxkIHVzZSB0aGUgYGJha2UoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlLg0KKFlvdSBnZW5lcmFsbHkgd2FudCB0byBsZWF2ZSB5b3VyIHRlc3RpbmcgZGF0YSBhbG9uZSwgYnV0IGl0IGlzIGdvb2QgdG8gbG9vayBmb3IgaXNzdWVzIGxpa2UgdGhlIGludHJvZHVjdGlvbiBvZiBOQSB2YWx1ZXMpLg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJ0ZXN0aW5nX3ByZXByb2Nlc3NpbmdfcmVjaXBlczQucG5nIikpDQpgYGANCg0KTGV0J3MgYmFrZSEgDQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCmBgYHtyLH0NCiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCENCmJha2VkX3Rlc3RfcG0gPC0gcmVjaXBlczo6YmFrZShwcmVwcGVkX3JlYywgbmV3X2RhdGEgPSB0ZXN0X3BtKQ0KZ2xpbXBzZShiYWtlZF90ZXN0X3BtKQ0KYGBgDQojIyMjDQoNCg0KTm90aWNlIHRoYXQgb3VyIGBjaXR5X05vdC5pbi5hLmNpdHlgIHZhcmlhYmxlIHNlZW1zIHRvIGJlIE5BIHZhbHVlcy4gDQpXaHkgbWlnaHQgdGhhdCBiZT8NCg0KQWghIFBlcmhhcHMgaXQgaXMgYmVjYXVzZSBzb21lIG9mIG91ciBsZXZlbHMgd2VyZSBub3QgcHJldmlvdXNseSBzZWVuIGluIHRoZSB0cmFpbmluZyBzZXQhDQoNCkxldCdzIHRha2UgYSBsb29rIHVzaW5nIHRoZSBbc2V0IG9wZXJhdGlvbnNdKGh0dHBzOi8vd3d3LnByb2JhYmlsaXR5Y291cnNlLmNvbS9jaGFwdGVyMS8xXzJfMl9zZXRfb3BlcmF0aW9ucy5waHApe3RhcmdldD0iX2JsYW5rIn0gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gDQpXZSBjYW4gdGFrZSBhIGxvb2sgYXQgY2l0aWVzIHRoYXQgd2VyZSBkaWZmZXJlbnQgYmV0d2VlbiB0aGUgdGVzdCBhbmQgdHJhaW5pbmcgc2V0Lg0KDQpgYGB7cn0NCnRyYWluY2l0aWVzIDwtIHRyYWluX3BtICU+JSBkaXN0aW5jdChjaXR5KQ0KdGVzdGNpdGllcyA8LSB0ZXN0X3BtICU+JSBkaXN0aW5jdChjaXR5KQ0KDQojZ2V0IHRoZSBudW1iZXIgb2YgY2l0aWVzIHRoYXQgd2VyZSBkaWZmZXJlbnQNCmRpbShkcGx5cjo6c2V0ZGlmZih0cmFpbmNpdGllcywgdGVzdGNpdGllcykpDQoNCiNnZXQgdGhlIG51bWJlciBvZiBjaXRpZXMgdGhhdCBvdmVybGFwcGVkDQpkaW0oZHBseXI6OmludGVyc2VjdCh0cmFpbmNpdGllcywgdGVzdGNpdGllcykpDQpgYGANCg0KSW5kZWVkLCB0aGVyZSBhcmUgbG90cyBvZiBkaWZmZXJlbnQgY2l0aWVzIGluIG91ciB0ZXN0IGRhdGEgdGhhdCBhcmUgbm90IGluIG91ciB0cmFpbmluZyBkYXRhIQ0KDQoNClNvLCBsZXQncyBnbyBiYWNrIHRvIG91ciBgcG1gIGRhdGEgc2V0IGFuZCBtb2RpZnkgdGhlIGBjaXR5YCB2YXJpYWJsZSB0byBqdXN0IGJlIHZhbHVlcyBvZiBgaW4gYSBjaXR5YCBvciBgbm90IGluIGEgY2l0eWAgdXNpbmcgdGhlIGBjYXNlX3doZW4oKWAgZnVuY3Rpb24gb2YgYGRwbHlyYC4NClRoaXMgZnVuY3Rpb24gYWxsb3dzIHlvdSB0byB2ZWN0b3JpemUgbXVsdGlwbGUgYGlmX2Vsc2UoKWAgc3RhdGVtZW50cy4NCg0KYGBge3J9DQpwbSAlPiUNCiAgbXV0YXRlKGNpdHkgPSBjYXNlX3doZW4oY2l0eSA9PSAiTm90IGluIGEgY2l0eSIgfiAiTm90IGluIGEgY2l0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNpdHkgIT0gIk5vdCBpbiBhIGNpdHkiIH4gIkluIGEgY2l0eSIpKQ0KYGBgDQoNCkFsdGVybmF0aXZlbHkgeW91IGNvdWxkIGNyZWF0ZSBhIFtjdXN0b20gc3RlcCBmdW5jdGlvbl0oaHR0cHM6Ly9yZWNpcGVzLnRpZHltb2RlbHMub3JnL2FydGljbGVzL0N1c3RvbV9TdGVwcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHRvIGRvIHRoaXMgYW5kIGFkZCB0aGlzIHRvIHlvdXIgcmVjaXBlLCBidXQgdGhhdCBpcyBiZXlvbmQgdGhlIHNjb3BlIG9mIHRoaXMgY2FzZSBzdHVkeS4gDQoNCldlIHdpbGwgbmVlZCB0byByZXBlYXQgYWxsIHRoZSBzdGVwcyAoc3BsaXR0aW5nIHRoZSBkYXRhLCBwcmUtcHJvY2Vzc2luZywgZXRjKSBhcyB0aGUgbGV2ZWxzIG9mIG91ciB2YXJpYWJsZXMgaGF2ZSBub3cgY2hhbmdlZC4gDQoNCldoaWxlIHdlIGFyZSBkb2luZyB0aGlzLCB3ZSBtaWdodCBhbHNvIGhhdmUgdGhpcyBpc3N1ZSBmb3IgYGNvdW50eWAuIA0KDQpUaGUgYGNvdW50eWAgdmFyaWFibGVzIGFwcGVhcnMgdG8gZ2V0IGRyb3BwZWQgZHVlIHRvIGVpdGhlciBjb3JyZWxhdGlvbiBvciBuZWFyIHplcm8gdmFyaWFuY2UuIA0KDQpJdCBpcyBsaWtlbHkgZHVlIHRvIG5lYXIgemVybyB2YXJpYW5jZSBiZWNhdXNlIHRoaXMgaXMgdGhlIG1vcmUgZ3JhbnVsYXIgb2YgdGhlc2UgZ2VvZ3JhcGhpYyBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYW5kIGxpa2VseSBzcGFyc2UuDQoNCmBgYHtyfQ0KcG0gJTw+JQ0KICBtdXRhdGUoY2l0eSA9IGNhc2Vfd2hlbihjaXR5ID09ICJOb3QgaW4gYSBjaXR5IiB+ICJOb3QgaW4gYSBjaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2l0eSAhPSAiTm90IGluIGEgY2l0eSIgfiAiSW4gYSBjaXR5IikpDQoNCnNldC5zZWVkKDEyMzQpICMgc2FtZSBzZWVkIGFzIGJlZm9yZQ0KcG1fc3BsaXQgPC1yc2FtcGxlOjppbml0aWFsX3NwbGl0KGRhdGEgPSBwbSwgcHJvcCA9IDIvMykNCnBtX3NwbGl0DQogdHJhaW5fcG0gPC1yc2FtcGxlOjp0cmFpbmluZyhwbV9zcGxpdCkNCiB0ZXN0X3BtIDwtcnNhbXBsZTo6dGVzdGluZyhwbV9zcGxpdCkNCmBgYA0KDQoNCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30NCjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPg0KDQpTZWUgaWYgeW91IGNhbiBjb21lIHVwIHdpdGggdGhlIGNvZGUgZm9yIHRoZSBuZXcgcmVjaXBlLg0KDQojIyMjDQoNCioqKg0KDQo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBjb2RlIGZvciB0aGUgbmV3IHJlY2lwZS4gPC9zdW1tYXJ5Pg0KDQoNCmBgYHtyfQ0Kbm92ZWxfcmVjIDwtcmVjaXBlKHRyYWluX3BtKSAlPiUNCiAgICB1cGRhdGVfcm9sZShldmVyeXRoaW5nKCksIG5ld19yb2xlID0gInByZWRpY3RvciIpICU+JQ0KICAgIHVwZGF0ZV9yb2xlKHZhbHVlLCBuZXdfcm9sZSA9ICJvdXRjb21lIikgJT4lDQogICAgdXBkYXRlX3JvbGUoaWQsIG5ld19yb2xlID0gImlkIHZhcmlhYmxlIikgJT4lDQogICAgdXBkYXRlX3JvbGUoImZpcHMiLCBuZXdfcm9sZSA9ICJjb3VudHkgaWQiKSAlPiUNCiAgICBzdGVwX2R1bW15KHN0YXRlLCBjb3VudHksIGNpdHksIHpjdGEsIG9uZV9ob3QgPSBUUlVFKSAlPiUNCiAgICBzdGVwX2NvcnIoYWxsX251bWVyaWMoKSkgJT4lDQogICAgc3RlcF9uenYoYWxsX251bWVyaWMoKSkgDQpgYGANCjwvZGV0YWlscz4NCioqKg0KDQpgYGB7cn0NCm5vdmVsX3JlYw0KYGBgDQoNCg0KDQpOb3cgbGV0J3MgcmV0cmFpbiBvdXIgdHJhaW5pbmcgZGF0YSBhbmQgdHJ5IGJha2luZyBvdXIgdGVzdCBkYXRhLg0KDQoNCg0KIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQ0KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+DQoNCkRvIHlvdSByZWNhbGwgaG93IHRvIHByZS1wcm9jZXNzIGFuZCBleHRyYWN0IHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGE/DQoNCiMjIyMNCg0KKioqDQoNCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGFuc3dlci4gPC9zdW1tYXJ5Pg0KDQpgYGB7cn0NCnByZXBwZWRfcmVjIDwtIHByZXAobm92ZWxfcmVjLCB2ZXJib3NlID0gVFJVRSwgcmV0YWluID0gVFJVRSkNCmJha2VkX3RyYWluIDwtIGJha2UocHJlcHBlZF9yZWMsIG5ld19kYXRhID0gTlVMTCkNCmBgYA0KPC9kZXRhaWxzPiANCioqKg0KDQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCmBgYHtyfQ0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQ0KZ2xpbXBzZShiYWtlZF90cmFpbikNCmBgYA0KDQojIyMjDQoNCkFuZCBub3csIGxldCdzIHRyeSBiYWtpbmcgb3VyIHRlc3Qgc2V0IHRvIHNlZSBpZiB3ZSBzdGlsbCBoYXZlIGBOQWAgdmFsdWVzLg0KDQojIyMjIHsuc2Nyb2xsYWJsZSB9DQoNCmBgYHtyfQ0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQ0KYmFrZWRfdGVzdF9wbSA8LSByZWNpcGVzOjpiYWtlKHByZXBwZWRfcmVjLCBuZXdfZGF0YSA9IHRlc3RfcG0pDQoNCmdsaW1wc2UoYmFrZWRfdGVzdF9wbSkNCmBgYA0KDQojIyMjDQoNCkdyZWF0LCBub3cgd2Ugbm8gbG9uZ2VyIGhhdmUgYE5BYCB2YWx1ZXMhIDopDQoNCioqTm90ZSoqOiBpZiB5b3UgdXNlIHRoZSBza2lwIG9wdGlvbiBmb3Igc29tZSBvZiB0aGUgcHJlLXByb2Nlc3Npbmcgc3RlcHMsIGJlIGNhcmVmdWwuIA0KYGp1aWNlKClgIHdpbGwgc2hvdyBhbGwgb2YgdGhlIHJlc3VsdHMgaWdub3JpbmcgYHNraXAgPSBUUlVFYCAoYXMgeW91IGNhbiBzdGlsbCB1c2UgdGhpcyBmdW5jdGlvbiBpZiB5b3UgcGVyZmVyIGl0IHRvIGBiYWtlKClgKS4NCmBiYWtlKClgIHdpbGwgbm90IG5lY2Vzc2FyaWx5IGNvbmR1Y3QgdGhlc2Ugc3RlcHMgb24gdGhlIG5ldyBkYXRhLg0KDQoNCiMjICoqU3BlY2lmeWluZyB0aGUgbW9kZWwqKg0KKioqDQoNClNvIGZhciB3ZSBoYXZlIHVzZWQgdGhlIHBhY2thZ2VzIGByc2FtcGxlYCB0byBzcGxpdCB0aGUgZGF0YSBhbmQgYHJlY2lwZXNgIHRvIGFzc2lnbiB2YXJpYWJsZSB0eXBlcywgYW5kIHRvIHNwZWNpZnkgYW5kIHByZXAgb3VyIHByZS1wcm9jZXNzaW5nIChhcyB3ZWxsIGFzIHRvIG9wdGlvbmFsbHkgZXh0cmFjdCB0aGUgcHJlLXByb2Nlc3NlZCBkYXRhKS4NCg0KV2Ugd2lsbCBub3cgdXNlIHRoZSBgcGFyc25pcGAgcGFja2FnZSAod2hpY2ggaXMgc2ltaWxhciB0byB0aGUgcHJldmlvdXMgYGNhcmV0YCBwYWNrYWdlIC0gYW5kIGhlbmNlIHdoeSBpdCBpcyBuYW1lZCBhZnRlciB0aGUgdmVnZXRhYmxlKSB0byBzcGVjaWZ5IG91ciBtb2RlbC4NCg0KVGhlcmUgYXJlIGZvdXIgdGhpbmdzIHdlIG5lZWQgdG8gZGVmaW5lIGFib3V0IG91ciBtb2RlbDogIA0KDQoxLiBUaGUgKip0eXBlKiogb2YgbW9kZWwgKHVzaW5nIHNwZWNpZmljIGZ1bmN0aW9ucyBpbiBwYXJzbmlwIGxpa2UgYHJhbmRfZm9yZXN0KClgLCBgbG9naXN0aWNfcmVnKClgIGV0Yy4pICANCjIuIFRoZSBwYWNrYWdlIG9yICoqZW5naW5lKiogdGhhdCB3ZSB3aWxsIHVzZSB0byBpbXBsZW1lbnQgdGhlIHR5cGUgb2YgbW9kZWwgc2VsZWN0ZWQgKHVzaW5nIHRoZSBgc2V0X2VuZ2luZSgpYCBmdW5jdGlvbikgDQozLiBUaGUgKiptb2RlKiogb2YgbGVhcm5pbmcgLSBjbGFzc2lmaWNhdGlvbiBvciByZWdyZXNzaW9uICh1c2luZyB0aGUgYHNldF9tb2RlKClgIGZ1bmN0aW9uKSANCjQuIEFueSAqKmFyZ3VtZW50cyoqIG5lY2Vzc2FyeSBmb3IgdGhlIG1vZGVsL3BhY2thZ2Ugc2VsZWN0ZWQgKHVzaW5nIHRoZSBgc2V0X2FyZ3MoKWBmdW5jdGlvbiAtICBmb3IgZXhhbXBsZSB0aGUgYG10cnkgPWAgYXJndW1lbnQgZm9yIHJhbmRvbSBmb3Jlc3Qgd2hpY2ggaXMgdGhlIG51bWJlciBvZiB2YXJpYWJsZXMgdG8gYmUgdXNlZCBhcyBvcHRpb25zIGZvciBzcGxpdHRpbmcgYXQgZWFjaCB0cmVlIG5vZGUpDQoNCkxldCdzIHdhbGsgdGhyb3VnaCB0aGVzZSBzdGVwcyBvbmUgYnkgb25lLiANCkZvciBvdXIgY2FzZSwgd2UgYXJlIGdvaW5nIHRvIHN0YXJ0IG91ciBhbmFseXNpcyB3aXRoIGEgbGluZWFyIHJlZ3Jlc3Npb24gYnV0IHdlIHdpbGwgZGVtb25zdHJhdGUgaG93IHdlIGNhbiB0cnkgZGlmZmVyZW50IG1vZGVscy4NCg0KVGhlIGZpcnN0IHN0ZXAgaXMgdG8gZGVmaW5lIHdoYXQgdHlwZSBvZiBtb2RlbCB3ZSB3b3VsZCBsaWtlIHRvIHVzZS4gDQpTZWUgW2hlcmVdKGh0dHBzOi8vd3d3LnRpZHltb2RlbHMub3JnL2ZpbmQvcGFyc25pcC8pe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vZGVsaW5nIG9wdGlvbnMgaW4gYHBhcnNuaXBgLg0KDQoNCmBgYHtyfQ0KUE1fbW9kZWwgPC0gcGFyc25pcDo6bGluZWFyX3JlZygpICMgUE0gd2FzIHVzZWQgaW4gdGhlIG5hbWUgZm9yIHBhcnRpY3VsYXRlIG1hdHRlcg0KUE1fbW9kZWwNCmBgYA0KDQpPSy4gU28gZmFyLCBhbGwgd2UgaGF2ZSBkZWZpbmVkIGlzIHRoYXQgd2Ugd2FudCB0byB1c2UgYSBsaW5lYXIgcmVncmVzc2lvbi4uLiAgDQpMZXQncyB0ZWxsIGBwYXJzbmlwYCBtb3JlIGFib3V0IHdoYXQgd2Ugd2FudC4NCg0KV2Ugd291bGQgbGlrZSB0byB1c2UgdGhlIFtvcmRpbmFyeSBsZWFzdCBzcXVhcmVzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9PcmRpbmFyeV9sZWFzdF9zcXVhcmVzKSBtZXRob2QgdG8gZml0IG91ciBsaW5lYXIgcmVncmVzc2lvbi4gDQpTbyB3ZSB3aWxsIHRlbGwgYHBhcnNuaXBgIHRoYXQgd2Ugd2FudCB0byB1c2UgdGhlIGBsbWAgcGFja2FnZSB0byBpbXBsZW1lbnQgb3VyIGxpbmVhciByZWdyZXNzaW9uICh0aGVyZSBhcmUgbWFueSBvcHRpb25zIGFjdHVhbGx5IHN1Y2ggYXMgW2Byc3RhbmBdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yc3Rhbi92aWduZXR0ZXMvcnN0YW4uaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgW2BnbG1uZXRgXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2xtbmV0L2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0sIFtga2VyYXNgXShodHRwczovL2tlcmFzLnJzdHVkaW8uY29tLyl7dGFyZ2V0PSJfYmxhbmsifSwgYW5kIFtgc3BhcmtseXJgXShodHRwczovL3RoZXJpbnNwYXJrLmNvbS9zdGFydGluZy5odG1sI3N0YXJ0aW5nLXNwYXJrbHlyLWhlbGxvLXdvcmxkKXt0YXJnZXQ9Il9ibGFuayJ9KS4gU2VlIFtoZXJlXShodHRwczovL3BhcnNuaXAudGlkeW1vZGVscy5vcmcvcmVmZXJlbmNlL2xpbmVhcl9yZWcuaHRtbCkgZm9yIGEgZGVzY3JpcHRpb24gb2YgdGhlIGRpZmZlcmVuY2VzIGFuZCB1c2luZyB0aGVzZSBkaWZmZXJlbnQgZW5naW5lcyB3aXRoIGBwYXJzbmlwYC4NCg0KV2Ugd2lsbCBkbyBzbyBieSB1c2luZyB0aGUgYHNldF9lbmdpbmUoKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXJzbmlwYCBwYWNrYWdlLg0KDQpgYGB7cn0NCmxtX1BNX21vZGVsIDwtIA0KICBQTV9tb2RlbCAgJT4lDQogIHBhcnNuaXA6OnNldF9lbmdpbmUoImxtIikNCg0KbG1fUE1fbW9kZWwNCmBgYA0KDQpJbiBzb21lIGNhc2VzIHNvbWUgcGFja2FnZXMgY2FuIGRvIGVpdGhlciBjbGFzc2lmaWNhdGlvbiBvciBwcmVkaWN0aW9uLCBzbyBpdCBpcyBhIGdvb2QgaWRlYSB0byBzcGVjaWZ5IHdoaWNoIG1vZGUgeW91IGludGVuZCB0byBwZXJmb3JtLiANCkhlcmUsIHdlIGFpbSB0byBwcmVkaWN0IHRoZSBhaXIgcG9sbHV0aW9uLiANCllvdSBjYW4gZG8gdGhpcyB3aXRoIHRoZSBgc2V0X21vZGUoKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXJzbmlwYCBwYWNrYWdlLCBieSB1c2luZyBlaXRoZXIgYHNldF9tb2RlKCJjbGFzc2lmaWNhdGlvbiIpYCBvciBgc2V0X21vZGUoInJlZ3Jlc3Npb24iKWAuDQoNCmBgYHtyfQ0KbG1fUE1fbW9kZWwgPC0gDQogIFBNX21vZGVsICAlPiUNCiAgcGFyc25pcDo6c2V0X2VuZ2luZSgibG0iKSAlPiUNCiAgc2V0X21vZGUoInJlZ3Jlc3Npb24iKQ0KDQpsbV9QTV9tb2RlbA0KYGBgDQoNCiMjICoqRml0dGluZyB0aGUgbW9kZWwqKg0KKioqDQoNCldlIGNhbiAgdXNlIHRoZSBgcGFyc25pcGAgcGFja2FnZSB3aXRoIGEgbmV3ZXIgcGFja2FnZSBjYWxsZWQgYHdvcmtmbG93c2AgdG8gZml0IG91ciBtb2RlbC4gDQoNClRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlIGFsbG93cyB1cyB0byBrZWVwIHRyYWNrIG9mIGJvdGggb3VyIHByZS1wcm9jZXNzaW5nIHN0ZXBzIGFuZCBvdXIgbW9kZWwgc3BlY2lmaWNhdGlvbi4gSXQgYWxzbyBhbGxvd3MgdXMgdG8gaW1wbGVtZW50IGZhbmNpZXIgb3B0aW1pemF0aW9ucyBpbiBhbiBhdXRvbWF0ZWQgd2F5IGFuZCBpdCBjYW4gYWxzbyBoYW5kbGUgcG9zdC1wcm9jZXNzaW5nIG9wZXJhdGlvbnMuIA0KDQoNCldlIGJlZ2luIGJ5IGNyZWF0aW5nIGEgd29ya2Zsb3cgdXNpbmcgdGhlIGB3b3JrZmxvdygpYCBmdW5jdGlvbiBpbiB0aGUgYHdvcmtmbG93c2AgcGFja2FnZS4gDQoNCk5leHQsIHdlIHVzZSBgYWRkX3JlY2lwZSgpYCAob3VyIHByZS1wcm9jZXNzaW5nIHNwZWNpZmljYXRpb25zKSBhbmQgd2UgYWRkIG91ciBtb2RlbCB3aXRoIHRoZSBgYWRkX21vZGVsKClgIGZ1bmN0aW9uIC0tIGJvdGggZnVuY3Rpb25zIGZyb20gdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UuDQoNCioqTm90ZSoqOiBXZSBkbyBub3QgbmVlZCB0byBhY3R1YWxseSBgcHJlcCgpYCBvdXIgcmVjaXBlIGJlZm9yZSB1c2luZyB3b3JrZmxvd3MhDQoNCklmIHlvdSByZWNhbGwgYG5vdmVsX3JlY2AgaXMgdGhlIHJlY2lwZSB3ZSBwcmV2aW91c2x5IGNyZWF0ZWQgd2l0aCB0aGUgYHJlY2lwZXNgIHBhY2thZ2UgYW5kIGBsbV9QTV9tb2RlbGAgd2FzIGNyZWF0ZWQgd2hlbiB3ZSBzcGVjaWZpZWQgb3VyIG1vZGVsIHdpdGggdGhlIGBwYXJzbmlwYCBwYWNrYWdlLg0KSGVyZSwgd2UgY29tYmluZSBldmVyeXRoaW5nIHRvZ2V0aGVyIGludG8gYSB3b3JrZmxvdy4gDQoNCmBgYHtyfQ0KUE1fd2Zsb3cgPC13b3JrZmxvd3M6OndvcmtmbG93KCkgJT4lDQogICAgICAgICAgIHdvcmtmbG93czo6YWRkX3JlY2lwZShub3ZlbF9yZWMpICU+JQ0KICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9tb2RlbChsbV9QTV9tb2RlbCkNClBNX3dmbG93DQpgYGANCg0KQWgsIG5pY2UuIA0KTm90aWNlIGhvdyBpdCB0ZWxscyB1cyBhYm91dCBib3RoIG91ciBwcmUtcHJvY2Vzc2luZyBzdGVwcyBhbmQgb3VyIG1vZGVsIHNwZWNpZmljYXRpb25zLg0KDQpOZXh0LCB3ZSAicHJlcGFyZSB0aGUgcmVjaXBlIiAob3IgZXN0aW1hdGUgdGhlIHBhcmFtZXRlcnMpIGFuZCBmaXQgdGhlIG1vZGVsIHRvIG91ciB0cmFpbmluZyBkYXRhIGFsbCBhdCBvbmNlLiANClByaW50aW5nIHRoZSBvdXRwdXQsIHdlIGNhbiBzZWUgdGhlIGNvZWZmaWNpZW50cyBvZiB0aGUgbW9kZWwuDQoNCmBgYHtyfQ0KUE1fd2Zsb3dfZml0IDwtIHBhcnNuaXA6OmZpdChQTV93ZmxvdywgZGF0YSA9IHRyYWluX3BtKQ0KUE1fd2Zsb3dfZml0DQpgYGANCg0KDQo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byBzZWUgdGhlIHN0ZXBzIHRoYXQgdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UgcGVyZm9ybXMgdGhhdCB1c2VkIHRvIGJlIHJlcXVpcmVkIDwvc3VtbWFyeT4NCg0KUHJldmlvdXNseSwgdGhlIHByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIChgYmFrZWRfdHJhaW5gKSwgYXMgb3Bwb3NlZCB0byB0aGUgcmF3IHRyYWluaW5nIGRhdGEsIHdvdWxkIGJlIHJlcXVpcmVkIHRvIGZpdCB0aGUgbW9kZWwuDQoNCkluIHRoaXMgY2FzZSwgd2Ugd291bGQgYWN0dWFsbHkgYWxzbyBuZWVkIHRvIHdyaXRlIHRoZSBtb2RlbCBhZ2FpbiEgDQpSZWNhbGwgdGhhdCBgaWRgIGFuZCBgZmlwc2AgYXJlIElEIHZhcmlhYmxlcyBhbmQgdGhhdCBgdmFsdWVzYCBpcyBvdXIgb3V0Y29tZSBvZiBpbnRlcmVzdCAodGhlIGFpciBwb2xsdXRpb24gbWVhc3VyZSBhdCBlYWNoIG1vbml0b3IpLiBJdCBpcyBuaWNlIHRoYXQgYHdvcmtmbG93c2Aga2VlcHMgdHJhY2sgb2YgdGhpcyENCg0KYGBge3J9DQpiYWtlZF90cmFpbl9yZWFkeSA8LSBiYWtlZF90cmFpbiAlPiUgDQogIHNlbGVjdCgtaWQsIC1maXBzKQ0KDQpQTV9maXQgPC0gbG1fUE1fbW9kZWwgJT4lIA0KICBwYXJzbmlwOjpmaXQodmFsdWUgfi4sIGRhdGEgPSBiYWtlZF90cmFpbl9yZWFkeSkNCmBgYA0KDQo8L2RldGFpbHM+DQoNCiMjICoqQXNzZXNzaW5nIHRoZSBtb2RlbCBmaXQqKg0KKioqDQoNCkFmdGVyIHdlIGZpdCBvdXIgbW9kZWwsIHdlIGNhbiB1c2UgdGhlIGBicm9vbWAgcGFja2FnZSB0byBsb29rIGF0IHRoZSBvdXRwdXQgZnJvbSB0aGUgZml0dGVkIG1vZGVsIGluIGFuIGVhc3kvdGlkeSB3YXkuICAgDQoNClRoZSBgdGlkeSgpYCBmdW5jdGlvbiByZXR1cm5zIGEgdGlkeSBkYXRhIGZyYW1lIHdpdGggY29lZmZpY2llbnRzIGZyb20gdGhlIG1vZGVsIChvbmUgcm93IHBlciBjb2VmZmljaWVudCkuDQoNCk1hbnkgb3RoZXIgYGJyb29tYCBmdW5jdGlvbnMgY3VycmVudGx5IG9ubHkgd29yayB3aXRoIGBwYXJzbmlwYCBvYmplY3RzLCBub3QgcmF3IGB3b3JrZmxvd3NgIG9iamVjdHMuIA0KDQpIb3dldmVyLCB3ZSBjYW4gdXNlIHRoZSBgdGlkeWAgZnVuY3Rpb24gaWYgd2UgZmlyc3QgdXNlIHRoZSBgcHVsbF93b3JrZmxvd19maXQoKWAgZnVuY3Rpb24uDQoNCmBgYHtyfQ0Kd2Zsb3dvdXRwdXQgPC0gUE1fd2Zsb3dfZml0ICU+JSANCiAgcHVsbF93b3JrZmxvd19maXQoKSAlPiUgDQogIGJyb29tOjp0aWR5KCkgDQpgYGANCg0KDQpgYGB7cn0NCndmbG93b3V0cHV0DQpgYGANCg0KV2UgaGF2ZSBmaXQgb3VyIG1vZGVsIG9uIG91ciB0cmFpbmluZyBkYXRhLCB3aGljaCBtZWFucyB3ZSBoYXZlIGNyZWF0ZWQgYSBtb2RlbCB0byBwcmVkaWN0IHZhbHVlcyBvZiBhaXIgcG9sbHV0aW9uIGJhc2VkIG9uIHRoZSBwcmVkaWN0b3JzIHRoYXQgd2UgaGF2ZSBpbmNsdWRlZC4gWWF5IQ0KDQpPbmUgbGFzdCB0aGluZyBiZWZvcmUgd2UgbGVhdmUgdGhpcyBzZWN0aW9uLiANCldlIG9mdGVuIGFyZSBpbnRlcmVzdGVkIGluIGdldHRpbmcgYSBzZW5zZSBvZiB3aGljaCB2YXJpYWJsZXMgYXJlIHRoZSBtb3N0IGltcG9ydGFudCBpbiBvdXIgbW9kZWwuIA0KV2UgY2FuIGV4cGxvcmUgdGhlIHZhcmlhYmxlIGltcG9ydGFuY2UgdXNpbmcgdGhlIGB2aXAoKWAgZnVuY3Rpb24gb2YgdGhlIGB2aXBgIHBhY2thZ2UuIA0KVGhpcyBmdW5jdGlvbiBjcmVhdGVzIGEgYmFyIHBsb3Qgb2YgdmFyaWFibGUgaW1wb3J0YW5jZSBzY29yZXMgZm9yIGVhY2ggcHJlZGljdG9yIHZhcmlhYmxlIChvciBmZWF0dXJlKSBpbiBhIG1vZGVsLiANClRoZSBiYXIgcGxvdCBpcyBvcmRlcmVkIGJ5IGltcG9ydGFuY2UgKGhpZ2hlc3QgdG8gc21hbGxlc3QpLiANCg0KDQpOb3RpY2UgYWdhaW4gdGhhdCB3ZSBuZWVkIHRvIHVzZSB0aGUgYHB1bGxfd29ya2Zsb3dfZml0KClgIGZ1bmN0aW9uLg0KDQpMZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgdG9wIDEwIGNvbnRyaWJ1dGluZyB2YXJpYWJsZXM6DQoNCmBgYHtyfQ0KUE1fd2Zsb3dfZml0ICU+JSANCiAgcHVsbF93b3JrZmxvd19maXQoKSAlPiUgDQogIHZpcChudW1fZmVhdHVyZXMgPSAxMCkNCmBgYA0KDQpUaGUgc3RhdGUgaW4gd2hpY2ggdGhlIG1vbml0b3Igd2FzIGxvY2F0ZWQgYW5kIHRoZSBDTUFRIG1vZGVsIGFuZCB0aGUgYW9kIHNhdGVsbGl0ZSBpbmZvcm1hdGlvbiBhcHBlYXIgdG8gYmUgdGhlIG1vc3QgaW1wb3J0YW50IGZvciBwcmVkaWN0aW5nIHRoZSBhaXIgcG9sbHV0aW9uIGF0IGEgZ2l2ZW4gbW9uaXRvci4NCg0KIyMgKipNb2RlbCBwZXJmb3JtYW5jZSoqDQoqKioNCg0KSW4gdGhpcyBuZXh0IHNlY3Rpb24sIG91ciBnb2FsIGlzIHRvIGFzc2VzcyB0aGUgb3ZlcmFsbCBtb2RlbCBwZXJmb3JtYW5jZS4gDQpUaGUgd2F5IHdlIGRvIHRoaXMgaXMgdG8gY29tcGFyZSB0aGUgc2ltaWxhcml0eSBiZXR3ZWVuIHRoZSBwcmVkaWN0ZWQgZXN0aW1hdGVzIG9mIHRoZSBvdXRjb21lIHZhcmlhYmxlIHByb2R1Y2VkIGJ5IHRoZSBtb2RlbCBhbmQgdGhlIHRydWUgb3V0Y29tZSB2YXJpYWJsZSB2YWx1ZXMuIA0KDQpJZiB5b3UgcmVjYWxsIHRoZSBbV2hhdCBpcyBtYWNoaW5lIGxlYXJuaW5nP10oI3doYXRpc21sKSBzZWN0aW9uLCB3ZSBzaG93ZWQgaG93IHRvIHRoaW5rIGFib3V0IG1hY2hpbmUgbGVhcm5pbmcgKE1MKSBhcyBhbiBvcHRpbWl6YXRpb24gcHJvYmxlbSB0aGF0IHRyaWVzIHRvIG1pbmltaXplIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIG91ciBwcmVkaWN0ZWQgb3V0Y29tZSAkXGhhdHtZfSA9IGYoWCkkIGFuZCBhY3R1YWwgb3V0Y29tZSAkWSQgdXNpbmcgb3VyIGZlYXR1cmVzIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKSAkWCQgYXMgaW5wdXQgdG8gYSBmdW5jdGlvbiAkZiQgdGhhdCB3ZSB3YW50IHRvIGVzdGltYXRlLiANCg0KJCRkKFkgLSBcaGF0e1l9KSQkDQoNCkFzIG91ciBnb2FsIGluIHRoaXMgc2VjdGlvbiBpcyB0byBhc3Nlc3Mgb3ZlcmFsbCBtb2RlbCBwZXJmb3JtYW5jZSwgd2Ugd2lsbCBub3cgdGFsayBhYm91dCBkaWZmZXJlbnQgZGlzdGFuY2UgbWV0cmljcyB0aGF0IHlvdSBjYW4gdXNlLiANCg0KRmlyc3QsIGxldCdzIHB1bGwgb3V0IG91ciBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMgJFxoYXR7WX0gPSBmKFgpJCBmcm9tIHRoZSBtb2RlbHMgd2UgZml0ICh1c2luZyBkaWZmZXJlbnQgYXBwcm9hY2hlcykuIA0KDQoNCmBgYHtyfQ0Kd2ZfZml0IDwtIFBNX3dmbG93X2ZpdCAlPiUgDQogIHB1bGxfd29ya2Zsb3dfZml0KCkNCg0Kd2ZfZml0dGVkX3ZhbHVlcyA8LSBmaXR0ZWQod2ZfZml0W1siZml0Il1dKQ0KaGVhZCh3Zl9maXR0ZWRfdmFsdWVzKQ0KYGBgDQoNCkFsdGVybmF0aXZlbHksIHdlIGNhbiBnZXQgdGhlIGZpdHRlZCB2YWx1ZXMgdXNpbmcgdGhlIGBhdWdtZW50KClgIGZ1bmN0aW9uIG9mIHRoZSBgYnJvb21gIHBhY2thZ2UgdXNpbmcgdGhlIG91dHB1dCBmcm9tIGB3b3JrZmxvd3NgOiANCg0KYGBge3J9DQp3Zl9maXR0ZWRfdmFsdWVzIDwtIA0KICBicm9vbTo6YXVnbWVudCh3Zl9maXRbWyJmaXQiXV0sIGRhdGEgPSBiYWtlZF90cmFpbikgJT4lIA0KICBzZWxlY3QodmFsdWUsIC5maXR0ZWQ6LnN0ZC5yZXNpZCkNCg0KaGVhZCh3Zl9maXR0ZWRfdmFsdWVzKQ0KDQpgYGANCg0KTm90ZSB0aGF0IGJlY2F1c2Ugd2UgdXNlIHRoZSBhY3R1YWwgd29ya2Zsb3cgaGVyZSwgd2UgY2FuIChhbmQgYWN0dWFsbHkgbmVlZCB0bykgdXNlIHRoZSByYXcgZGF0YSBpbnN0ZWFkIG9mIHRoZSBwcmUtcHJvY2Vzc2VkIGRhdGEuDQoNCmBgYHtyfQ0KdmFsdWVzX3ByZWRfdHJhaW4gPC0gDQogIHByZWRpY3QoUE1fd2Zsb3dfZml0LCB0cmFpbl9wbSkgJT4lIA0KICBiaW5kX2NvbHModHJhaW5fcG0gJT4lIHNlbGVjdCh2YWx1ZSwgZmlwcywgY291bnR5LCBpZCkpIA0KDQp2YWx1ZXNfcHJlZF90cmFpbg0KDQpgYGANCg0KIyMjICoqVmlzdWFsaXppbmcgbW9kZWwgcGVyZm9ybWFuY2UqKg0KKioqDQoNCk5vdywgd2UgY2FuIGNvbXBhcmUgdGhlIHByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyAob3IgZml0dGVkIHZhbHVlcykgJFxoYXR7WX0kIHRvIHRoZSBhY3R1YWwgb3V0Y29tZSB2YWx1ZXMgJFkkIHRoYXQgd2Ugb2JzZXJ2ZWQ6IA0KDQpgYGB7cn0NCndmX2ZpdHRlZF92YWx1ZXMgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSAgdmFsdWUsIHkgPSAuZml0dGVkKSkgKyANCiAgZ2VvbV9wb2ludCgpICsgDQogIHhsYWIoImFjdHVhbCBvdXRjb21lIHZhbHVlcyIpICsgDQogIHlsYWIoInByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyIpDQpgYGANCg0KT0ssIHNvIG91ciByYW5nZSBvZiB0aGUgcHJlZGljdGVkIG91dGNvbWUgdmFsdWVzIGFwcGVhcnMgdG8gYmUgc21hbGxlciB0aGFuIHRoZSByZWFsIHZhbHVlcy4gDQpXZSBjb3VsZCBwcm9iYWJseSBkbyBhIGJpdCBiZXR0ZXIuDQoNCiMjIyAqKlF1YW50aWZ5aW5nIG1vZGVsIHBlcmZvcm1hbmNlKioNCioqKg0KDQpOZXh0LCBsZXQncyB1c2UgZGlmZmVyZW50IGRpc3RhbmNlIGZ1bmN0aW9ucyAkZChcY2RvdCkkIHRvIGFzc2VzcyBob3cgZmFyIG9mZiBvdXIgcHJlZGljdGVkIG91dGNvbWUgJFxoYXR7WX0gPSBmKFgpJCBhbmQgYWN0dWFsIG91dGNvbWUgJFkkIHZhbHVlcyBhcmUgZnJvbSBlYWNoIG90aGVyOiANCg0KJCRkKFkgLSBcaGF0e1l9KSQkDQoNCkFzIG1lbnRpb25lZCwgdGhlcmUgYXJlIGVudGlyZSBzY2hvbGFybHkgZmllbGRzIG9mIHJlc2VhcmNoIGRlZGljYXRlZCB0byBpZGVudGlmeWluZyBkaWZmZXJlbnQgZGlzdGFuY2UgbWV0cmljcyAkZChcY2RvdCkkIGZvciBtYWNoaW5lIGxlYXJuaW5nIGFwcGxpY2F0aW9ucy4gDQpIb3dldmVyLCB3aGVuIHBlcmZvcm1pbmcgcHJlZGljdGlvbiB3aXRoIGEgY29udGludW91cyBvdXRjb21lICRZJCwgYSBmZXcgb2YgdGhlIG1vc3RseSBjb21tb25seSB1c2VkIGRpc3RhbmNlIG1ldHJpY3MgYXJlOiANCg0KMS4gbWVhbiBhYnNvbHV0ZSBlcnJvciAoYG1hZWApICANCg0KJCRNQUUgPSBcZnJhY3tcc3VtX3tpPTF9XntufXsofFxoYXR7eV90fS0geV90fCl9XjJ9e259JCQNCg0KDQoyLiBSIHNxdWFyZWQgZXJyb3IgKGByc3FgKSAtLSB0aGlzIGlzIGFsc28ga25vd24gYXMgdGhlIGNvZWZmaWNpZW50IG9mIGRldGVybWluYXRpb24gd2hpY2ggaXMgdGhlIHNxdWFyZWQgY29ycmVsYXRpb24gYmV0d2VlbiB0cnV0aCBhbmQgZXN0aW1hdGUNCg0KVGhpcyBpcyBjYWxjdWxhdGVkIGFuZCAxIG1pbnVzIHRoZSBmcmFjdGlvbiBvZiB0aGUgcmVzaWR1YWwgc3VtIG9mIHNxdWFyZXMgKCRTU19yZXMkKSBieSB0aGUgdG90YWwgc3VtIG9mIHNxdWFyZXMgKCRTU190b3QkKQ0KDQoNCiQkUlNRID0gUl4yID0gMSAtIFxmcmFje1NTcmVzfXtTU3RvdH0kJA0KDQokJFNTX3t0b3R9ID0gXHN1bV97aT0xfV57bn17KHlfaS0gXGJhcnt5fSl9XjIkJA0KVGhlIHRvdGFsIHN1bSBvZiBzcXVhcmVzIGlzIHByb3BvcnRpb25hbCB0byB0aGUgdmFyaWFuY2Ugb2YgdGhlIGRhdGEuIEl0IGlzIGNhbGN1bGF0ZWQgYXMgdGhlIHN1bSBvZiBlYWNoICB0cnVlIHZhbHVlIGZyb20gdGhlIG1lYW4gdHJ1ZSB2YWx1ZSAoJFxiYXJ7eX0kKS4NCg0KJCRTU197cmVzfSA9IFxzdW1fe2k9MX1ee259eyh5X2ktIFxoYXR7eV9pfSl9XjIkJA0KDQpUaGUgc3VtIG9mIHNxdWFyZXMgb2YgcmVzaWR1YWxzIGlzIGNhbGN1bGF0ZWQgYXMgdGhlIHN1bSBvZiBlYWNoIHByZWRpY3RlZCB2YWx1ZSAoJFxoYXR7eV9pfSQgb3Igc29tZXRpbWVzICRmX2kkKSBmcm9tIHRoZSB0cnVlIHZhbHVlICgkeV9pJCkuIA0KDQoNCjMuIFtyb290IG1lYW4gc3F1YXJlZCBlcnJvcl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUm9vdC1tZWFuLXNxdWFyZV9kZXZpYXRpb24pe3RhcmdldD0iX2JsYW5rIn0gKGBybXNlYCkgICANCg0KJCRSTVNFID0gXHNxcnR7XGZyYWN7XHN1bV97aT0xfV57bn17KFxoYXR7eV90fS0geV90KX1eMn17bn19JCQNCg0KDQoNCg0KT25lIHdheSB0byBjYWxjdWxhdGUgdGhlc2UgbWV0cmljcyB3aXRoaW4gdGhlIGB0aWR5bW9kZWxzYCBmcmFtZXdvcmsgaXMgdG8gdXNlIHRoZSBgeWFyZHN0aWNrYCBwYWNrYWdlIHVzaW5nIHRoZSBgbWV0cmljcygpYCBmdW5jdGlvbi4gDQoNCmBgYHtyfQ0KeWFyZHN0aWNrOjptZXRyaWNzKHdmX2ZpdHRlZF92YWx1ZXMsIA0KICAgICAgICAgICAgICAgICAgIHRydXRoID0gdmFsdWUsIGVzdGltYXRlID0gLmZpdHRlZCkNCmBgYA0KDQpBbHRlcm5hdGl2ZWx5IGlmIHlvdSBvbmx5IHdhbnRlZCBvbmUgbWV0cmljIHlvdSBjb3VsZCB1c2UgdGhlIGBtYWUoKWAsIGByc3EoKWAsIG9yIGBybXNlKClgIGZ1bmN0aW9ucywgcmVzcGVjdGl2ZWx5LiANCg0KYGBge3J9DQp5YXJkc3RpY2s6Om1hZSh3Zl9maXR0ZWRfdmFsdWVzLCANCiAgICAgICAgICAgICAgIHRydXRoID0gdmFsdWUsIGVzdGltYXRlID0gLmZpdHRlZCkNCmBgYA0KDQojIyAqKkNyb3NzIHZhbGlkYXRpb24qKg0KKioqDQoNClVudGlsIG5vdyB3ZSBoYXZlIHVzZWQgZXZlcnl0aGluZyBpbiBvdXIgInRyYWluaW5nIiBkYXRhc2V0IChhbmQgaGF2ZSBub3QgdG91Y2hlZCB0aGUgInRlc3RpbmciIGRhdGFzZXQpIGZyb20gdGhlIGByc2FtcGxlYCBwYWNrYWdlIHRvIGJ1aWxkIG91ciBtYWNoaW5lIGxlYXJuaW5nIChNTCkgbW9kZWwgJFxoYXR7WX0gPSBmKFgpJCAob3IgdG8gZXN0aW1hdGUgJGYkIHVzaW5nIHRoZSBmZWF0dXJlcyBvciBwcmVkaWN0b3IgdmFyaWFibGUgJFgkKS4gDQoNCkhlcmUsIHdlIHRha2UgdGhpcyBiZXlvbmQgdGhlIHNpbXBsZSBzcGxpdCBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEgc2V0cy4gDQpXZSB3aWxsIHVzZSB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgYWdhaW4gaW4gb3JkZXIgdG8gZnVydGhlciBpbXBsZW1lbnQgd2hhdCBhcmUgY2FsbGVkIFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSB0ZWNobmlxdWVzLiBUaGlzIGlzIGFsc28gY2FsbGVkICoqcmUtc2FtcGxpbmcqKiBvciAqKnJlcGFydGlvbmluZyoqLiAgDQoNCioqTm90ZSoqOiB3ZSBhcmUgbm90IGFjdHVhbGx5IGdldHRpbmcgbmV3IHNhbXBsZXMgZnJvbSB0aGUgdW5kZXJseWluZyBkaXN0cmlidXRpb24gc28gdGhlIHRlcm0gcmUtc2FtcGxpbmcgaXMgYSBiaXQgb2YgYSBtaXNub21lci4NCg0KW0Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IHNwbGl0cyBvdXIgdHJhaW5pbmcgZGF0YSBpbnRvIG11bHRpcGxlIHRyYWluaW5nIGRhdGEgc2V0cyB0byBhbGxvdyBmb3IgYSBkZWVwZXIgYXNzZXNzbWVudCBvZiB0aGUgYWNjdXJhY3kgb2YgdGhlIG1vZGVsLg0KDQpIZXJlIGlzIGEgdmlzdWFsaXphdGlvbiBvZiB0aGUgY29uY2VwdCBmb3IgY3Jvc3MgdmFsaWRhdGlvbi9yZXNhbXBsaW5nL3JlcGFydGl0aW9uaW5nIGZyb20gW01heCBLdWhuXShodHRwczovL3Jlc291cmNlcy5yc3R1ZGlvLmNvbS9hdXRob3JzL21heC1rdWhuKXt0YXJnZXQ9Il9ibGFuayJ9Og0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJyZXNhbXBsaW5nLnBuZyIpKQ0KYGBgDQoNClRlY2huaWNhbGx5IGNyZWF0aW5nIG91ciB0ZXN0aW5nIGFuZCB0cmFpbmluZyBzZXQgb3V0IG9mIG91ciBvcmlnaW5hbCB0cmFpbmluZyBkYXRhIGlzIHNvbWV0aW1lcyBjb25zaWRlcmVkIGEgZm9ybSBvZiBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0sIGNhbGxlZCB0aGUgaG9sZG91dCBtZXRob2QuIA0KVGhlIHJlYXNvbiB3ZSBkbyB0aGlzIGl0IHNvIHdlIGNhbiBnZXQgYSBiZXR0ZXIgc2Vuc2Ugb2YgdGhlIGFjY3VyYWN5IG9mIG91ciBtb2RlbCB1c2luZyBkYXRhIHRoYXQgd2UgZGlkIG5vdCB0cmFpbiBpdCBvbi4gDQoNCkhvd2V2ZXIsIHdlIGNhbiBhY3R1YWxseSBkbyBhIGJldHRlciBqb2Igb2Ygb3B0aW1pemluZyBvdXIgbW9kZWwgZm9yIGFjY3VyYWN5IGlmIHdlIGFsc28gcGVyZm9ybSBhbm90aGVyIHR5cGUgb2YgW2Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IG9uIHRoZSBuZXdseSBkZWZpbmVkIHRyYWluaW5nIHNldCB0aGF0IHdlIGp1c3QgY3JlYXRlZC4gDQpUaGVyZSBhcmUgbWFueSBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gbWV0aG9kcyBhbmQgbW9zdCBjYW4gYmUgZWFzaWx5IGltcGxlbWVudGVkIHVzaW5nIGByc2FtcGxlYCBwYWNrYWdlLiANCkhlcmUsIHdlIHdpbGwgdXNlIGEgdmVyeSBwb3B1bGFyIG1ldGhvZCBjYWxsZWQgZWl0aGVyIFtrLWZvbGQgb3Igdi1mb2xkIGNyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vay1mb2xkLWNyb3NzLXZhbGlkYXRpb24vKXt0YXJnZXQ9Il9ibGFuayJ9LiANCg0KVGhpcyBtZXRob2QgaW52b2x2ZXMgZXNzZW50aWFsbHkgcHJlZm9ybWluZyB0aGUgaG9sZCBvdXQgbWV0aG9kIGl0ZXJhdGl2ZWx5IHdpdGggdGhlIHRyYWluaW5nIGRhdGEuIA0KDQpGaXJzdCwgdGhlIHRyYWluaW5nIHNldCBpcyBkaXZpZGVkIGludG8gJHYkIChvciBvZnRlbiBjYWxsZWQgY2FsbGVkICRrJCkgZXF1YWxseSBzaXplZCBzbWFsbGVyIHBpZWNlcy4gDQoNCk5leHQsIHRoZSBtb2RlbCBpcyB0cmFpbmVkIG9uIHRoZSBtb2RlbCBvbiAkdiQtMSBzdWJzZXRzIG9mIHRoZSBkYXRhIGl0ZXJhdGl2ZWx5IChyZW1vdmluZyBhIGRpZmZlcmVudCAkdiQgdW50aWwgYWxsIHBvc3NpYmxlICR2JC0xIHNldHMgaGF2ZSBiZWVuIGV2YWx1YXRlZCkgdG8gZ2V0IGEgc2Vuc2Ugb2YgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBtb2RlbC4gDQpUaGlzIGlzIHJlYWxseSB1c2VmdWwgZm9yIGZpbmUgdHVuaW5nIHNwZWNpZmljIGFzcGVjdHMgb2YgdGhlIG1vZGVsIGluIGEgcHJvY2VzcyBjYWxsZWQgbW9kZWwgdHVuaW5nLCB3aGljaCB3ZSB3aWxsIGxlYXJuIGFib3V0IGluIHRoZSBuZXh0IHNlY3Rpb24uIA0KDQpIZXJlIGlzIGEgdmlzdWFsaXphdGlvbiBvZiBob3cgdGhlIGZvbGRzIGFyZSBjcmVhdGVkOg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAidmZvbGQucG5nIikpDQpgYGANCg0KKipOb3RlKio6IFBlb3BsZSB0eXBpY2FsbHkgaWdub3JlIHNwYXRpYWwgZGVwZW5kZW5jZSB3aXRoIGNyb3NzIHZhbGlkYXRpb24gb2YgYWlyIHBvbGx1dGlvbiBtb25pdG9yaW5nIGRhdGEgaW4gdGhlIGFpciBwb2xsdXRpb24gZmllbGQsIHNvIHdlIHdpbGwgZG8gdGhlIHNhbWUuICBIb3dldmVyLCBpdCBtaWdodCBtYWtlIHNlbnNlIHRvIGxlYXZlIG91dCBibG9ja3Mgb2YgbW9uaXRvcnMgcmF0aGVyIHRoYW4gIHJhbmRvbSBpbmRpdmlkdWFsIG1vbml0b3JzIHRvIGhlbHAgYWNjb3VudCBmb3Igc29tZSBzcGF0aWFsIGRlcGVuZGVuY2UuDQoNCiMjIyAqKkNyZWF0aW5nIHRoZSAkdiQtZm9sZHMgdXNpbmcgYHJzYW1wbGVgKioNCioqKg0KDQpUaGUgW2B2Zm9sZF9jdigpYF0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yc2FtcGxlL3JlZmVyZW5jZS92Zm9sZF9jdi5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZ1bmN0aW9uIG9mIHRoZSBgcnNhbXBsZWAgcGFja2FnZSBjYW4gYmUgdXNlZCB0byBwYXJzZSB0aGUgdHJhaW5pbmcgZGF0YSBpbnRvIGZvbGRzIGZvciAkdiQtZm9sZCBjcm9zcyB2YWxpZGF0aW9uLg0KDQotIFRoZSBgdmAgYXJndW1lbnQgc3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgZm9sZHMgdG8gY3JlYXRlLg0KLSBUaGUgYHJlcGVhdHNgIGFyZ3VtZW50IHNwZWNpZmllcyBpZiBhbnkgc2FtcGxlcyBzaG91bGQgYmUgcmVwZWF0ZWQgYWNyb3NzIGZvbGRzIC0gZGVmYXVsdCBpcyBgRkFMU0VgDQotIFRoZSBgc3RyYXRhYCBhcmd1bWVudCBzcGVjaWZpZXMgYSB2YXJpYWJsZSB0byBzdHJhdGlmeSBzYW1wbGVzIGFjcm9zcyBmb2xkcyAtIGp1c3QgbGlrZSBpbiBgaW5pdGlhbF9zcGxpdCgpYC4NCg0KQWdhaW4sIGJlY2F1c2UgdGhlc2UgYXJlIGNyZWF0ZWQgYXQgcmFuZG9tLCB3ZSBuZWVkIHRvIHVzZSB0aGUgYmFzZSBgc2V0LnNlZWQoKWAgZnVuY3Rpb24gaW4gb3JkZXIgdG8gb2J0YWluIHRoZSBzYW1lIHJlc3VsdHMgZWFjaCB0aW1lIHdlIGtuaXQgdGhpcyBkb2N1bWVudC4gDQpHZW5lcmFsbHkgc3BlYWtpbmcgdXNpbmcgMTAgZm9sZHMgaXMgZ29vZCBwcmFjdGljZSwgYnV0IHRoaXMgZGVwZW5kcyBvbiB0aGUgdmFyaWFiaWxpdHkgd2l0aGluIHlvdXIgZGF0YS4gDQpXZSBhcmUgZ29pbmcgdG8gdXNlIDQgZm9yIHRoZSBzYWtlIG9mIGV4cGVkaWVuY3kuIA0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMzQpDQp2Zm9sZF9wbSA8LSByc2FtcGxlOjp2Zm9sZF9jdihkYXRhID0gdHJhaW5fcG0sIHYgPSA0KQ0KdmZvbGRfcG0NCnB1bGwodmZvbGRfcG0sIHNwbGl0cykNCmBgYA0KDQpOb3cgd2UgY2FuIHNlZSB0aGF0IHdlIGhhdmUgY3JlYXRlZCA0IGZvbGRzIG9mIHRoZSBkYXRhIGFuZCB3ZSBjYW4gc2VlIGhvdyBtYW55IHZhbHVlcyB3ZXJlIHNldCBhc2lkZSBmb3IgdGVzdGluZyAoY2FsbGVkIGFzc2Vzc2luZyBmb3IgY3Jvc3MgdmFsaWRhdGlvbiBzZXRzKSBhbmQgdHJhaW5pbmcgKGNhbGxlZCBhbmFseXNpcyBmb3IgY3Jvc3MgdmFsaWRhdGlvbiBzZXRzKSB3aXRoaW4gZWFjaCBmb2xkLg0KDQpPbmNlIHRoZSBmb2xkcyBhcmUgY3JlYXRlZCB0aGV5IGNhbiBiZSB1c2VkIHRvIGV2YWx1YXRlIHBlcmZvcm1hbmNlIGJ5IGZpdHRpbmcgdGhlIG1vZGVsIHRvIGVhY2ggb2YgdGhlIHJlLXNhbXBsZXMgdGhhdCB3ZSBjcmVhdGVkOg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiY3Jvc3NfdmFsaWRhdGlvbi5wbmciKSkNCmBgYA0KDQojIyMgKipBc3Nlc3NpbmcgbW9kZWwgcGVyZm9ybWFuY2Ugb24gJHYkLWZvbGRzIHVzaW5nIGB0dW5lYCoqDQoqKioNCg0KV2UgY2FuIGZpdCB0aGUgbW9kZWwgdG8gb3VyIGNyb3NzIHZhbGlkYXRpb24gZm9sZHMgdXNpbmcgdGhlIGBmaXRfcmVzYW1wbGVzKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZSwgYnkgc3BlY2lmeWluZyBvdXIgYHdvcmtmbG93YCBvYmplY3QgYW5kIHRoZSBjcm9zcyB2YWxpZGF0aW9uIGZvbGQgb2JqZWN0IHdlIGp1c3QgY3JlYXRlZC4gDQpTZWUgW2hlcmVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vdHVuZS9yZWZlcmVuY2UvZml0X3Jlc2FtcGxlcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uLg0KDQoNCmBgYHtyfQ0KcmVzYW1wbGVfZml0IDwtIHR1bmU6OmZpdF9yZXNhbXBsZXMoUE1fd2Zsb3csIHZmb2xkX3BtKQ0KYGBgDQoNCldlIGNhbiBub3cgdGFrZSBhIGxvb2sgYXQgdmFyaW91cyBwZXJmb3JtYW5jZSBtZXRyaWNzIGJhc2VkIG9uIHRoZSBmaXQgb2Ygb3VyIGNyb3NzIHZhbGlkYXRpb24gInJlc2FtcGxlcyIuIA0KVG8gZG8gdGhpcyB3ZSB3aWxsIHVzZSB0aGUgYHNob3dfYmVzdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UuDQoNCmBgYHtyfQ0KdHVuZTo6c2hvd19iZXN0KHJlc2FtcGxlX2ZpdCwgbWV0cmljID0gInJtc2UiKQ0KYGBgDQoNCkhlcmUgd2UgY2FuIHNlZSB0aGUgbWVhbiBgUk1TRWAgdmFsdWUgYWNyb3NzIGFsbCBmb3VyIGZvbGRzLiBUaGUgZnVuY3Rpb24gaXMgY2FsbGVkIGBzaG93X2Jlc3QoKWAgYmVjYXVzZSBpdCBpcyBhbHNvIHVzZWQgZm9yIG1vZGVsIHR1bmluZyBhbmQgaXQgd2lsbCBzaG93IHRoZSBwYXJhbWV0ZXIgY29tYmluYXRpb24gd2l0aCB0aGUgYmVzdCBwZXJmb3JtYW5jZSwgd2Ugd2lsbCBkaXNjdXNzIHRoaXMgbW9yZSBsYXRlciBpbiB0aGUgY2FzZSBzdHVkeS4NCg0KIyMgKipFeGVyY2lzZSoqDQoqKioNCg0KPCEtLS1BUF9NTF9RdWl6LS0+DQoNCjxpZnJhbWUgc3R5bGU9Im1hcmdpbjowIGF1dG87IG1pbi13aWR0aDogMTAwJTsiIGlkPSJBUF9NTF9RdWl6SWZyYW1lIiBjbGFzcz0iaW50ZXJhY3RpdmUiIHNyYz0iaHR0cHM6Ly9yc2Nvbm5lY3QuYmlvc3RhdC5qaHNwaC5lZHUvT0NTX0FQX01MX1F1aXovIiBzY3JvbGxpbmc9Im5vIiBmcmFtZWJvcmRlcj0ibm8iPjwvaWZyYW1lPg0KDQo8IS0tLS0tLS0tLS0tLS0tLS0+DQoNCiMgKipEYXRhIEFuYWx5c2lzKioNCioqKg0KDQpJbiB0aGUgcHJldmlvdXMgc2VjdGlvbiwgd2UgZGVtb25zdHJhdGVkIGhvdyB0byBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWwgKHNwZWNpZmljYWxseSBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsKSB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gd2l0aCB0aGUgYHRpZHltb2RlbHNgIGZyYW1ld29yay4gDQoNCkluIHRoZSBuZXh0IGZldyBzZWN0aW9uLCB3ZSB3aWxsIGRlbW9uc3RyYXRlIGFub3RoZXIgbWFjaGluZSBsZWFybmluZyBtb2RlbC4gDQoNCg0KIyMgKipSYW5kb20gRm9yZXN0KioNCioqKg0KDQpOb3csIHdlIGFyZSBnb2luZyB0byBwcmVkaWN0IG91ciBvdXRjb21lIHZhcmlhYmxlIChhaXIgcG9sbHV0aW9uKSB1c2luZyBhIGRlY2lzaW9uIHRyZWUgbWV0aG9kIGNhbGxlZCBbcmFuZG9tIGZvcmVzdF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUmFuZG9tX2ZvcmVzdCl7dGFyZ2V0PSJfYmxhbmsifS4NCg0KQSBbZGVjaXNpb24gdHJlZV0oaHR0cHM6Ly9tZWRpdW0uY29tL2dyZXlhdG9tL2RlY2lzaW9uLXRyZWVzLWEtc2ltcGxlLXdheS10by12aXN1YWxpemUtYS1kZWNpc2lvbi1kYzUwNmE0MDNhZWIpe3RhcmdldD0iX2JsYW5rIn0gaXMgYSB0b29sIHRvIHBhcnRpdGlvbiBkYXRhIG9yIGFueXRoaW5nIHJlYWxseSwgYmFzZWQgb24gYSBzZXJpZXMgb2Ygc2VxdWVudGlhbCAob2Z0ZW4gYmluYXJ5KSBkZWNpc2lvbnMsIHdoZXJlIHRoZSBkZWNpc2lvbnMgYXJlIGNob3NlbiBiYXNlZCBvbiB0aGVpciBhYmlsaXR5IHRvIG9wdGltYWxseSBzcGxpdCB0aGUgZGF0YS4NCg0KSGVyZSB5b3UgY2FuIHNlZSBhIHNpbXBsZSBleGFtcGxlOg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vbWlyby5tZWRpdW0uY29tL21heC8xMDAwLzEqTE1vSm1YQ3NRbGNpR1RFeW9TTjM5Zy5qcGVnIikNCmBgYA0KDQojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS91bmRlcnN0YW5kaW5nLXJhbmRvbS1mb3Jlc3QtNTgzODFlMDYwMmQyKXt0YXJnZXQ9Il9ibGFuayJ9DQoNCkluIHRoZSBjYXNlIG9mIFtyYW5kb20gZm9yZXN0XShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vZGVjaXNpb24tdHJlZS1lbnNlbWJsZXMtYmFnZ2luZy1hbmQtYm9vc3RpbmctMjY2YThiYTYwZmQ5KXt0YXJnZXQ9Il9ibGFuayJ9LCBtdWx0aXBsZSBkZWNpc2lvbiB0cmVlcyBhcmUgY3JlYXRlZCAtIGhlbmNlIHRoZSBuYW1lIGZvcmVzdCwgYW5kIGVhY2ggdHJlZSBpcyBidWlsdCB1c2luZyBhIHJhbmRvbSBzdWJzZXQgb2YgdGhlIHRyYWluaW5nIGRhdGEgKHdpdGggcmVwbGFjZW1lbnQpIC0gaGVuY2UgdGhlIGZ1bGwgbmFtZSByYW5kb20gZm9yZXN0LiBUaGlzIHJhbmRvbSBhc3BlY3QgaGVscHMgdG8ga2VlcCB0aGUgYWxnb3JpdGhtIGZyb20gb3ZlcmZpdHRpbmcgdGhlIGRhdGEuDQoNClRoZSBtZWFuIG9mIHRoZSBwcmVkaWN0aW9ucyBmcm9tIGVhY2ggb2YgdGhlIHRyZWVzIGlzIHVzZWQgaW4gdGhlIGZpbmFsIG91dHB1dC4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL21pcm8ubWVkaXVtLmNvbS9tYXgvMTQwMC8wKmZfcVFQRnBkb2ZXR0xRcWMucG5nIikNCmBgYA0KDQoNCkluIG91ciBjYXNlLCB3ZSBhcmUgZ29pbmcgdG8gdXNlIHRoZSByYW5kb20gZm9yZXN0IG1ldGhvZCBvZiB0aGUgdGhlIGByYW5kb21Gb3Jlc3RgIHBhY2thZ2UuIA0KDQpUaGlzIHBhY2thZ2UgaXMgY3VycmVudGx5IG5vdCBjb21wYXRpYmxlIHdpdGggY2F0ZWdvcmljYWwgdmFyaWFibGVzIHRoYXQgaGF2ZSBtb3JlIHRoYW4gNTMgbGV2ZWxzLiBTZWUgW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yYW5kb21Gb3Jlc3QvTkVXUykgZm9yIHRoZSBkb2N1bWVudGF0aW9uIGFib3V0IHdoZW4gdGhpcyB3YXMgdXBkYXRlZCBmcm9tIDI1IGxldmVscy4gVGh1cyB3ZSB3aWxsIHJlbW92ZSB0aGUgYHpjdGFgICBhbmQgYGNvdW50eWAgdmFyaWFibGVzLg0KDQpOb3RlIHRoYXQgdGhlIGBzdGVwX25vdmVsKClgIGZ1bmN0aW9uIGlzIG5lY2Vzc2FyeSBoZXJlIGZvciB0aGUgYHN0YXRlYCB2YXJpYWJsZSB0byBnZXQgYWxsIGNyb3NzIHZhbGlkYXRpb24gZm9sZHMgdG8gd29yaywgYmVjYXVzZSB0aGVyZSB3aWxsIGJlIGRpZmZlcmVudCBsZXZlbHMgaW5jbHVkZWQgaW4gZWFjaCBmb2xkIHRlc3QgYW5kIHRyYWluaW5nIHNldHMuIFRoZSBuZXcgbGV2ZWxzIGZvciBzb21lIG9mIHRoZSB0ZXN0IHNldHMgd291bGQgb3RoZXJ3aXNlIHJlc3VsdCBpbiBhbiBlcnJvci4NCg0KQWNjb3JkaW5nIHRvIHRoZSBbZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3JlY2lwZXMvdmVyc2lvbnMvMC4xLjEzL3RvcGljcy9zdGVwX25vdmVsKSBmb3IgdGhlIGByZWNpcGVzYCBwYWNrYWdlOg0KDQo+IHN0ZXBfbm92ZWwgY3JlYXRlcyBhIHNwZWNpZmljYXRpb24gb2YgYSByZWNpcGUgc3RlcCB0aGF0IHdpbGwgYXNzaWduIGEgcHJldmlvdXNseSB1bnNlZW4gZmFjdG9yIGxldmVsIHRvIGEgbmV3IHZhbHVlLg0KDQpgYGB7cn0NClJGX3JlYyA8LSByZWNpcGUodHJhaW5fcG0pICU+JQ0KICAgIHVwZGF0ZV9yb2xlKGV2ZXJ5dGhpbmcoKSwgbmV3X3JvbGUgPSAicHJlZGljdG9yIiklPiUNCiAgICB1cGRhdGVfcm9sZSh2YWx1ZSwgbmV3X3JvbGUgPSAib3V0Y29tZSIpJT4lDQogICAgdXBkYXRlX3JvbGUoaWQsIG5ld19yb2xlID0gImlkIHZhcmlhYmxlIikgJT4lDQogICAgdXBkYXRlX3JvbGUoImZpcHMiLCBuZXdfcm9sZSA9ICJjb3VudHkgaWQiKSAlPiUNCiAgICBzdGVwX25vdmVsKCJzdGF0ZSIpICU+JQ0KICAgIHN0ZXBfc3RyaW5nMmZhY3Rvcigic3RhdGUiLCAiY291bnR5IiwgImNpdHkiKSAlPiUNCiAgICBzdGVwX3JtKCJjb3VudHkiKSAlPiUNCiAgICBzdGVwX3JtKCJ6Y3RhIikgJT4lDQogICAgc3RlcF9jb3JyKGFsbF9udW1lcmljKCkpJT4lDQogICAgc3RlcF9uenYoYWxsX251bWVyaWMoKSkNCmBgYA0KDQpUaGUgYHJhbmRfZm9yZXN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZSBoYXMgdGhyZWUgaW1wb3J0YW50IGFyZ3VtZW50cyB0aGF0IGFjdCBhcyBhbiBpbnRlcmZhY2UgZm9yIHRoZSBkaWZmZXJlbnQgcG9zc2libGUgZW5naW5lcyB0byBwZXJmb3JtIGEgcmFuZG9tIGZvcmVzdCBhbmFseXNpczoNCg0KMS4gYG10cnlgIC0gVGhlIG51bWJlciBvZiBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykgdGhhdCB3aWxsIGJlIHJhbmRvbWx5IHNhbXBsZWQgYXQgZWFjaCBzcGxpdCB3aGVuIGNyZWF0aW5nIHRoZSB0cmVlIG1vZGVscy4gVGhlIGRlZmF1bHQgbnVtYmVyIGZvciByZWdyZXNzaW9uIGFuYWx5c2VzIGlzIHRoZSBudW1iZXIgb2YgcHJlZGljdG9ycyBkaXZpZGVkIGJ5IDMuIA0KMi4gYG1pbl9uYCAtIFRoZSBtaW5pbXVtIG51bWJlciBvZiBkYXRhIHBvaW50cyBpbiBhIG5vZGUgdGhhdCBhcmUgcmVxdWlyZWQgZm9yIHRoZSBub2RlIHRvIGJlIHNwbGl0IGZ1cnRoZXIuDQozLiBgdHJlZXNgIC0gdGhlIG51bWJlciBvZiB0cmVlcyBpbiB0aGUgZW5zZW1ibGUNCg0KV2Ugd2lsbCBzdGFydCBieSB0cnlpbmcgYW4gYG10cnlgIHZhbHVlIG9mIDEwIGFuZCBhIGBtaW5fbmAgdmFsdWUgb2YgMy4NCg0KTm93IHRoYXQgd2UgaGF2ZSBvdXIgcmVjaXBlIChgUkZfcmVjYCksIGxldCdzIHNwZWNpZnkgdGhlIG1vZGVsIHdpdGggYHJhbmRfZm9yZXN0KClgIGZyb20gYHBhcnNuaXBgLg0KDQpgYGB7cn0NClBNdHJlZV9tb2RlbCA8LSANCiAgcGFyc25pcDo6cmFuZF9mb3Jlc3QobXRyeSA9IDEwLCBtaW5fbiA9IDMpDQpQTXRyZWVfbW9kZWwNCmBgYA0KDQpOZXh0LCB3ZSBzZXQgdGhlIGVuZ2luZSBhbmQgbW9kZToNCg0KTm90ZSB0aGF0IHlvdSBjb3VsZCBhbHNvIHVzZSB0aGUgYHJhbmdlcmAgb3IgYHNwYXJrYCBwYWNrYWdlcyBpbnN0ZWFkIG9mIGByYW5kb21Gb3Jlc3RgLg0KSWYgeW91IHdlcmUgdG8gdXNlIHRoZSBgcmFuZ2VyYCBwYWNrYWdlIHRvIGltcGxlbWVudCB0aGUgcmFuZG9tIGZvcmVzdCBhbmFseXNpcyB5b3Ugd291bGQgbmVlZCB0byBzcGVjaWZ5IGFuIGBpbXBvcnRhbmNlYCBhcmd1bWVudCB0byBiZSBhYmxlIHRvIGV2YWx1YXRlIHByZWRpY3RvciBpbXBvcnRhbmNlLiAgVGhlIG9wdGlvbnMgYXJlIGBpbXB1cml0eWAgb3IgYHBlcm11dGF0aW9uYC4NCg0KVGhlc2Ugb3RoZXIgcGFja2FnZXMgaGF2ZSBkaWZmZXJlbnQgYWR2YW50YWdlcyBhbmQgZGlzYWR2YW50YWdlcy0gZm9yIGV4YW1wbGUgYHJhbmdlcmAgYW5kIGBzcGFya2AgYXJlIG5vdCBhcyBsaW1pdGluZyBmb3IgdGhlIG51bWJlciBvZiBjYXRlZ29yaWVzIGZvciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuIEZvciBtb3JlIGluZm9ybWF0aW9uIHNlZSB0aGVpciBkb2N1bWVudGF0aW9uOiBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3Jhbmdlci9yYW5nZXIucGRmKSBmb3IgYHJhbmdlcmAsIFtoZXJlXShodHRwOi8vc3BhcmsuYXBhY2hlLm9yZy9kb2NzL2xhdGVzdC9tbGxpYi1lbnNlbWJsZXMuaHRtbCNyYW5kb20tZm9yZXN0cykgZm9yIGBzcGFya2AsIGFuZCBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JhbmRvbUZvcmVzdC9yYW5kb21Gb3Jlc3QucGRmKSBmb3IgYHJhbmRvbUZvcmVzdGAuDQoNClNlZSBbaGVyZV0oaHR0cHM6Ly9wYXJzbmlwLnRpZHltb2RlbHMub3JnL3JlZmVyZW5jZS9yYW5kX2ZvcmVzdC5odG1sKSBmb3IgbW9yZSBkb2N1bWVudGF0aW9uIGFib3V0IGltcGxlbWVudGluZyB0aGVzZSBlbmdpbmUgb3B0aW9ucyB3aXRoIHRpZHltb2RlbHMuIE5vdGUgdGhhdCB0aGVyZSBhcmUgYWxzbyBbb3RoZXJdKGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9wdWxzZS9kaWZmZXJlbnQtcmFuZG9tLWZvcmVzdC1wYWNrYWdlcy1yLW1hZGh1ci1tb2RpLykgUiBwYWNrYWdlcyBmb3IgaW1wbGVtZW50aW5nIHJhbmRvbSBmb3Jlc3QgYWxnb3JpdGhtcywgYnV0IHRoZXNlIHRocmVlIHBhY2thZ2VzIChgcmFuZ2VyYCwgYHNwYXJrYCwgYW5kIGByYW5kb21Gb3Jlc3RgKSBhcmUgY3VycmVudGx5IGNvbXBhdGlibGUgd2l0aCBgdGlkeW1vZGVsc2AuDQoNCldlIGFsc28gbmVlZCB0byBzcGVjaWZ5IHdpdGggdGhlIGBzZXRfbW9kZSgpYCBmdW5jdGlvbiB0aGF0IG91ciBvdXRjb21lIHZhcmlhYmxlIChhaXIgcG9sbHV0aW9uKSBpcyBjb250aW51b3VzLiANCg0KYGBge3J9DQoNClJGX1BNX21vZGVsIDwtIA0KICBQTXRyZWVfbW9kZWwgJT4lDQogIHNldF9lbmdpbmUoInJhbmRvbUZvcmVzdCIpICU+JQ0KICBzZXRfbW9kZSgicmVncmVzc2lvbiIpDQoNClJGX1BNX21vZGVsDQpgYGANCg0KVGhlbiwgd2UgcHV0IHRoaXMgYWxsIHRvZ2V0aGVyIGludG8gYSBgd29ya2Zsb3dgOiANCg0KIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQ0KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+DQoNClNlZSBpZiB5b3UgY2FuIGNvbWUgdXAgd2l0aCB0aGUgY29kZSB0byBkbyB0aGlzLg0KDQojIyMjDQoNCioqKg0KPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+DQoNCmBgYHtyfQ0KUkZfd2Zsb3cgPC0gd29ya2Zsb3dzOjp3b3JrZmxvdygpICU+JQ0KICAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfcmVjaXBlKFJGX3JlYykgJT4lDQogICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9tb2RlbChSRl9QTV9tb2RlbCkNCg0KYGBgDQo8L2RldGFpbHM+IA0KKioqDQoNCmBgYHtyfQ0KUkZfd2Zsb3cNCmBgYA0KDQoNCkZpbmFsbHksIHdlIGZpdCB0aGUgZGF0YSB0byB0aGUgbW9kZWw6DQoNCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30NCjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPg0KDQpEbyB5b3UgcmVjYWxsIGhvdyB0byBkbyB0aGlzPw0KDQojIyMjDQoNCioqKg0KPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+DQoNCmBgYHtyfQ0KUkZfd2Zsb3dfZml0IDwtIHBhcnNuaXA6OmZpdChSRl93ZmxvdywgZGF0YSA9IHRyYWluX3BtKQ0KYGBgDQo8L2RldGFpbHM+IA0KKioqDQoNCmBgYHtyfQ0KUkZfd2Zsb3dfZml0DQpgYGANCg0KTGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIHRvcCAxMCBjb250cmlidXRpbmcgdmFyaWFibGVzOg0KDQojIyMjIHsucmVjYWxsX2NvZGVfcXVlc3Rpb25fYmxvY2t9DQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4NCg0KU2VlIGlmIHlvdSBjYW4gcmVjYWxsIGhvdyB0byBkbyB0aGlzLg0KDQojIyMjDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpSRl93Zmxvd19maXQgJT4lIA0KICBwdWxsX3dvcmtmbG93X2ZpdCgpICU+JSANCiAgdmlwKG51bV9mZWF0dXJlcyA9IDEwKQ0KDQpgYGANCg0KDQoqKioNCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGFuc3dlci4gPC9zdW1tYXJ5Pg0KDQpgYGB7cn0NClJGX3dmbG93X2ZpdCAlPiUgDQogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIA0KICB2aXAobnVtX2ZlYXR1cmVzID0gMTApDQpgYGANCjwvZGV0YWlscz4NCioqKg0KDQoNCkludGVyZXN0aW5nISBJbiB0aGUgcHJldmlvdXMgbW9kZWwgdGhlIENNQVEgdmFsdWVzIGFuZCB0aGUgc3RhdGUgd2hlcmUgdGhlIG1vbml0b3Igd2FzIGxvY2F0ZWQgd2VyZSBhbHNvIHRoZSB0b3AgdHdvIG1vc3QgaW1wb3J0YW50LCBob3dldmVyIHByZWRpY3RvcnMgYWJvdXQgZWR1Y2F0aW9uIGxldmVscyBvZiB0aGUgY29tbXVuaXRpZXMgd2hlcmUgdGhlIG1vbml0b3Igd2FzIGxvY2F0ZWQgd2FzIGFtb25nIHRoZSB0b3AgbW9zdCBpbXBvcnRhbnQuIE5vdyB3ZSBzZWUgdGhhdCBwb3B1bGF0aW9uIGRlbnNpdHkgYW5kIHByb3hpbWl0eSB0byBzb3VyY2VzIG9mIGVtaXNzaW9ucyBhbmQgcm9hZHMgYXJlIGFtb25nIHRoZSB0b3AgdGVuLg0KDQoNCk5vdyBsZXQncyB0YWtlIGEgbG9vayBhdCBtb2RlbCBwZXJmb3JtYW5jZSBieSBmaXR0aW5nIHRoZSBkYXRhIHVzaW5nIGNyb3NzIHZhbGlkYXRpb246DQoNCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30NCjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPg0KDQpTZWUgaWYgeW91IGNhbiByZWNhbGwgaG93IHRvIGRvIHRoaXMuDQoNCiMjIyMNCg0KKioqDQo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4NCg0KYGBge3IsIGV2YWwgPSBGQUxTRX0NCnNldC5zZWVkKDQ1NikNCnJlc2FtcGxlX1JGX2ZpdCA8LSB0dW5lOjpmaXRfcmVzYW1wbGVzKFJGX3dmbG93LCB2Zm9sZF9wbSkNCmNvbGxlY3RfbWV0cmljcyhyZXNhbXBsZV9SRl9maXQpDQpgYGANCg0KPC9kZXRhaWxzPg0KKioqDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQpzZXQuc2VlZCg0NTYpDQpyZXNhbXBsZV9SRl9maXQgPC0gdHVuZTo6Zml0X3Jlc2FtcGxlcyhSRl93ZmxvdywgdmZvbGRfcG0pDQpjb2xsZWN0X21ldHJpY3MocmVzYW1wbGVfUkZfZml0KQ0KYGBgDQoNCk5vdyBsZXQncyBjb21wYXJlIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGlzIG1vZGVsIHdpdGggb3VyIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsOg0KDQpgYGB7cn0NCiMgb3VyIGluaXRpYWwgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWw6DQpjb2xsZWN0X21ldHJpY3MocmVzYW1wbGVfZml0KQ0KYGBgDQoNCk9LLCBzbyBvdXIgZmlyc3QgbW9kZWwgaGFkIGEgbWVhbiBgcm1zZWAgdmFsdWUgb2YgMi4xNy4NCkl0IGxvb2tzIGxpa2UgdGhlIHJhbmRvbSBmb3Jlc3QgbW9kZWwgaGFkICBhIG11Y2ggbG93ZXIgYHJtc2VgIHZhbHVlIG9mIDEuNzIuDQoNCiMjIyMgey50aGlua19xdWVzdGlvbl9ibG9ja30NCjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPg0KDQpEbyB5b3UgcmVjYWxsIGhvdyB0aGUgUk1TRSBpcyBjYWxjdWxhdGVkPw0KDQojIyMjDQoNCioqKg0KDQo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4NCiQkUk1TRSA9IFxzcXJ0e1xmcmFje1xzdW1fe2k9MX1ee259eyhcaGF0e3lfdH0tIHlfdCl9XjJ9e259fSQkDQo8L2RldGFpbHM+IA0KKioqDQoNCklmIHdlIHR1bmVkIG91ciByYW5kb20gZm9yZXN0IG1vZGVsIGJhc2VkIG9uIHRoZSBudW1iZXIgb2YgdHJlZXMgb3IgdGhlIHZhbHVlIGZvciBgbXRyeWAgKHdoaWNoIGlzICJUaGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgdGhhdCB3aWxsIGJlIHJhbmRvbWx5IHNhbXBsZWQgYXQgZWFjaCBzcGxpdCB3aGVuIGNyZWF0aW5nIHRoZSB0cmVlIG1vZGVscyIpLCB3ZSBtaWdodCBnZXQgYSBtb2RlbCB3aXRoIGV2ZW4gYmV0dGVyIHBlcmZvcm1hbmNlLg0KDQpIb3dldmVyLCBvdXIgY3Jvc3MgdmFsaWRhdGVkIG1lYW4gcm1zZSB2YWx1ZSBvZiAxLjcyIGlzIHF1aXRlIGdvb2QgYmVjYXVzZSBvdXIgcmFuZ2Ugb2YgdHJ1ZSBvdXRjb21lIHZhbHVlcyBpcyBtdWNoIGxhcmdlcjogKGByIHJvdW5kKHJhbmdlKHRlc3RfcG0kdmFsdWUpLDMpYCkuDQoNCg0KIyMgKipNb2RlbCB0dW5pbmcqKg0KKioqDQoNCltIeXBlcnBhcmFtZXRlcnNdKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vZGlmZmVyZW5jZS1iZXR3ZWVuLWEtcGFyYW1ldGVyLWFuZC1hLWh5cGVycGFyYW1ldGVyLykgYXJlIG9mdGVuIHRoaW5ncyB0aGF0IHdlIG5lZWQgdG8gc3BlY2lmeSBhYm91dCBhIG1vZGVsLiBGb3IgZXhhbXBsZSwgdGhlIG51bWJlciBvZiBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykgdGhhdCB3aWxsIGJlIHJhbmRvbWx5IHNhbXBsZWQgYXQgZWFjaCBzcGxpdCB3aGVuIGNyZWF0aW5nIHRoZSB0cmVlIG1vZGVscyBjYWxsZWQgYG10cnlgIGlzIGEgaHlwZXJwYXJhbWV0ZXIuIFRoZSBkZWZhdWx0IG51bWJlciBmb3IgcmVncmVzc2lvbiBhbmFseXNlcyBpcyB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgZGl2aWRlZCBieSAzLiBJbnN0ZWFkIG9mIGFyYml0cmFyaWx5IHNwZWNpZnlpbmcgdGhpcywgd2UgY2FuIHRyeSB0byBkZXRlcm1pbmUgdGhlIGJlc3Qgb3B0aW9uIGZvciBtb2RlbCBwZXJmb3JtYW5jZSBieSBhIHByb2Nlc3MgY2FsbGVkIHR1bmluZy4gDQoNCg0KTm93IGxldCdzIHRyeSBzb21lIHR1bmluZy4NCg0KTGV0J3MgdGFrZSBhIGNsb3NlciBsb29rIGF0IHRoZSBgbXRyeWAgYW5kIGBtaW5fbmAgaHlwZXJwYXJhbWV0cnMgaW4gb3VyIFJhbmRvbSBGb3Jlc3QgbW9kZWwuDQoNCldlIGFyZW4ndCBleGFjdGx5IHN1cmUgd2hhdCB2YWx1ZXMgb2YgYG10cnlgIGFuZCBgbWluX25gIGFjaGlldmUgZ29vZCBhY2N1cmFjeSB5ZXQga2VlcCBvdXIgbW9kZWwgZ2VuZXJhbGl6YWJsZSBmb3Igb3RoZXIgZGF0YS4NCg0KVGhpcyBpcyB3aGVuIG91ciBjcm9zcyB2YWxpZGF0aW9uIG1ldGhvZHMgYmVjb21lIHJlYWxseSBoYW5keSBiZWNhdXNlIG5vdyB3ZSBjYW4gdGVzdCBvdXQgZGlmZmVyZW50IHZhbHVlcyBmb3IgZWFjaCBvZiB0aGVzZSBoeXBlcnBhcmFtZXRlcnMgdG8gYXNzZXNzIHdoYXQgdmFsdWVzIHNlZW0gdG8gd29yayBiZXN0IGZvciBtb2RlbCBwZXJmb3JtYW5jZSBvbiB0aGVzZSByZXNhbXBsZXMgb2Ygb3VyIHRyYWluaW5nIHNldCBkYXRhLg0KDQpQcmV2aW91c2x5IHdlIHNwZWNpZmllZCBvdXIgbW9kZWwgbGlrZSBzbzoNCmBgYHtyfQ0KUkZfUE1fbW9kZWwgPC0gDQogIHBhcnNuaXA6OnJhbmRfZm9yZXN0KG10cnkgPSAxMCwgbWluX24gPSAzKSAlPiUNCiAgc2V0X2VuZ2luZSgicmFuZG9tRm9yZXN0IikgJT4lDQogIHNldF9tb2RlKCJyZWdyZXNzaW9uIikNCg0KUkZfUE1fbW9kZWwNCmBgYA0KTm93IGluc3RlYWQgb2Ygc3BlY2lmeWluZyBhIHZhbHVlIGZvciB0aGUgYG10cnlgIGFuZCBgbWluX25gIGFyZ3VtZW50cywgd2UgY2FuIHVzZSB0aGUgYHR1bmUoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIGxpa2Ugc286IGBtdHJ5ID0gdHVuZSgpYC4gVGhpcyBpbmRpY2F0ZXMgdGhhdCB0aGVzZSBoeXBlcnBhcmFtZXRlcnMgYXJlIHRvIGJlIHR1bmVkLiANCg0KYGBge3J9DQoNCnR1bmVfUkZfbW9kZWwgPC0gcmFuZF9mb3Jlc3QobXRyeSA9IHR1bmUoKSwgbWluX24gPSB0dW5lKCkpICU+JQ0KICBzZXRfZW5naW5lKCJyYW5kb21Gb3Jlc3QiKSAlPiUNCiAgc2V0X21vZGUoInJlZ3Jlc3Npb24iKQ0KICAgIA0KDQp0dW5lX1JGX21vZGVsDQoNCmBgYA0KDQoNCkFnYWluIHdlIHdpbGwgYWRkIHRoaXMgdG8gYSB3b3JrZmxvdywgdGhlIG9ubHkgZGlmZmVyZW5jZSBoZXJlIGlzIHRoYXQgd2UgYXJlIHVzaW5nIGEgZGlmZmVyZW50IG1vZGVsIHNwZWNpZmljYXRpb24gd2l0aCBgdHVuZV9SRl9tb2RlbGAgaW5zdGVhZCBvZiBgUkZfbW9kZWxgOg0KDQpgYGB7cn0NCg0KUkZfdHVuZV93ZmxvdyA8LSB3b3JrZmxvd3M6OndvcmtmbG93KCkgJT4lDQogICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9yZWNpcGUoUkZfcmVjKSAlPiUNCiAgICAgICAgICAgIHdvcmtmbG93czo6YWRkX21vZGVsKHR1bmVfUkZfbW9kZWwpDQpSRl90dW5lX3dmbG93DQoNCmBgYA0KDQoNCk5vdyB3ZSBjYW4gdXNlIHRoZSBgdHVuZV9ncmlkKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZSB0byBldmFsdWF0ZSBkaWZmZXJlbnQgY29tYmluYXRpb25zIG9mIHZhbHVlcyBmb3IgYG10cnlgIGFuZCBgbWluX25gIHVzaW5nIG91ciBjcm9zcyB2YWxpZGF0aW9uIHNhbXBsZXMgb2Ygb3VyIHRyYWluaW5nIHNldCAoYHZmb2xkX3BtYCkgdG8gc2VlIHdoYXQgY29tYmluYXRpb24gb2YgdmFsdWVzIHBlcmZvcm1zIGJlc3QuDQoNClRvIHVzZSB0aGlzIGZ1bmN0aW9uIHdlIHdpbGwgc3BlY2lmeSB0aGUgd29ya2Zsb3cgdXNpbmcgdGhlIGBvYmplY3RgIGFyZ3VtZW50ICBhbmQgdGhlIHNhbXBsZXMgdG8gdXNlIHVzaW5nIHRoZSBgcmVzYW1wbGVzYCBhcmd1bWVudC4gVGhlIGBncmlkYCBhcmd1bWVudCBzcGVjaWZpZXMgaG93IG1hbnkgcG9zc2libGUgb3B0aW9ucyBmb3IgZWFjaCBhcmd1bWVudCBzaG91bGQgYmUgYXR0ZW1wdGVkLg0KDQpCeSBkZWZhdWx0IDEwIGRpZmZlcmVudCB2YWx1ZXMgd2lsbCBiZSBhdHRlbXB0ZWQgZm9yIGVhY2ggaHlwZXJwYXJhbWV0ZXIgdGhhdCBpcyBiZWluZyB0dW5lZC4NCg0KV2UgY2FuIHVzZSB0aGUgYGRvUGFyYWxsZWxgIHBhY2thZ2UgdG8gYWxsb3cgdXMgdG8gZml0IGFsbCB0aGVzZSBtb2RlbHMgdG8gb3VyIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcyBmYXN0ZXIuIFNvIGlmIHlvdSB3ZXJlIHBlcmZvcm1pbmcgdGhpcyBvbiBhIGNvbXB1dGVyIHdpdGggbXVsdGlwbGUgY29yZXMgb3IgcHJvY2Vzc29ycywgdGhlbiBkaWZmZXJlbnQgbW9kZWxzIHdpdGggZGlmZmVyZW50IGh5cGVycGFyYW1ldGVyIHZhbHVlcyBjYW4gYmUgZml0IHRvIHRoZSBjcm9zcyB2YWxpZGF0aW9uIHNhbXBsZXMgc2ltdWx0YW5lb3VzbHkgYWNyb3NzIGRpZmZlcmVudCBjb3JlcyBvciBwcm9jZXNzb3JzLiANCg0KWW91IGNhbiBzZWUgaG93IG1hbnkgY29yZXMgeW91IGhhdmUgYWNjZXNzIHRvIG9uIHlvdXIgc3lzdGVtIHVzaW5nIHRoZSBgZGV0ZWN0Q29yZXMoKWAgZnVuY3Rpb24gaW4gdGhlIGBwYXJhbGxlbGAgcGFja2FnZS4gDQoNCmBgYHtyfQ0KcGFyYWxsZWw6OmRldGVjdENvcmVzKCkNCmBgYA0KDQpUaGUgYHJlZ2lzdGVyRG9QYXJhbGxlbCgpYCBmdW5jdGlvbiB3aWxsIHVzZSB0aGUgbnVtYmVyIGZvciBjb3JlcyBzcGVjaWZpZWQgdXNpbmcgdGhlIGBjb3Jlcz1gIGFyZ3VlbWVudCwgb3IgaXQgd2lsbCBhc3NpZ24gaXQgYXV0b21hdGljYWxseSB0byBvbmUtaGFsZiBvZiB0aGUgbnVtYmVyIG9mIGNvcmVzIGRldGVjdGVkIGJ5IHRoZSBgcGFyYWxsZWxgIHBhY2thZ2UuIA0KDQpXZSBuZWVkIHRvIHVzZSBgc2V0LnNlZWQoKWAgaGVyZSBiZWNhdXNlIHRoZSB2YWx1ZXMgY2hvc2VuIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgbWF5IHZhcnkgaWYgd2UgcHJlZm9ybSB0aGlzIGV2YWx1YXRpb24gYWdhaW4gYmVjYXVzZSB0aGV5IGFyZSBjaG9zZW4gc2VtaS1yYW5kb21seSAobWVhbmluZyB0aGF0IHRoZXkgYXJlIHdpdGhpbiBhIHJhbmdlIG9mIHJlYXNvbmFibGUgdmFsdWVzIGJ1dCBzdGlsbCByYW5kb20pLg0KDQpOb3RlOiB0aGlzIHN0ZXAgd2lsbCB0YWtlIHNvbWUgdGltZS4NCg0KYGBge3J9DQpkb1BhcmFsbGVsOjpyZWdpc3RlckRvUGFyYWxsZWwoY29yZXM9MikNCnNldC5zZWVkKDEyMykNCnR1bmVfUkZfcmVzdWx0cyA8LSB0dW5lX2dyaWQob2JqZWN0ID0gUkZfdHVuZV93ZmxvdywgcmVzYW1wbGVzID0gdmZvbGRfcG0sIGdyaWQgPSAyMCkNCnR1bmVfUkZfcmVzdWx0cw0KYGBgDQoNCg0KU2VlIFt0aGUgdHVuZSBnZXR0aW5nIHN0YXJ0ZWQgZ3VpZGUgXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3R1bmUvYXJ0aWNsZXMvZ2V0dGluZ19zdGFydGVkLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgaW1wbGVtZW50aW5nIHRoaXMgaW4gYHRpZHltb2RlbHNgLg0KDQpJZiB5b3Ugd2FudGVkIG1vcmUgY29udHJvbCBvdmVyIHRoaXMgcHJvY2VzcyB5b3UgY291bGQgc3BlY2lmeSBob3cgdGhlIGRpZmZlcmVudCBwb3NzaWJsZSBvcHRpb25zIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgaW4gdGhlIGB0dW5lX2dyaWQoKWAgZnVuY3Rpb24gdXNpbmcgdGhlIGBncmlkXyooKWAgZnVuY3Rpb25zIG9mIHRoZSBgZGlhbHNgIHBhY2thZ2UgdG8gY3JlYXRlIGEgbW9yZSBzcGVjaWZpYyBncmlkLg0KDQpCeSBkZWZhdWx0IHRoZSB2YWx1ZXMgZm9yIHRoZSBoeXBlcnBhcmFtZXRlcnMgYmVpbmcgdHVuZWQgYXJlIGNob3NlbiBzZW1pLXJhbmRvbWx5IChtZWFuaW5nIHRoYXQgdGhleSBhcmUgd2l0aGluIGEgcmFuZ2Ugb2YgcmVhc29uYWJsZSB2YWx1ZXMgYnV0IHN0aWxsIHJhbmRvbSkuLg0KDQoNCk5vdyB3ZSBjYW4gdXNlIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIGFnYWluIHRvIHRha2UgYSBsb29rIGF0IHdoYXQgaGFwcGVuZWQgd2l0aCBvdXIgY3Jvc3MgdmFsaWRhdGlvbiB0ZXN0cy4gV2UgY2FuIHNlZSB0aGUgZGlmZmVyZW50IHZhbHVlcyBjaG9zZW4gZm9yIGBtdHJ5YCBhbmQgYG1pbl9uYCBhbmQgdGhlIG1lYW4gcm1zZSBhbmQgcnNxIHZhbHVlcyBhY3Jvc3MgdGhlIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcy4NCg0KYGBge3J9DQp0dW5lX1JGX3Jlc3VsdHMlPiUNCiAgY29sbGVjdF9tZXRyaWNzKCkNCmBgYA0KDQpXZSBjYW4gbm93IHVzZSB0aGUgYHNob3dfYmVzdCgpYCBmdW5jdGlvbiBhcyBpdCB3YXMgdHJ1bHkgaW50ZW5kZWQsIHRvIHNlZSB3aGF0IHZhbHVlcyBmb3IgYG1pbl9uYCBhbmQgYG10cnlgIHJlc3VsdGVkIGluIHRoZSBiZXN0IHBlcmZvcm1hbmNlLg0KDQpgYGB7cn0NCnNob3dfYmVzdCh0dW5lX1JGX3Jlc3VsdHMsIG1ldHJpYyA9ICJybXNlIiwgbiA9MSkNCmBgYA0KVGhlcmUgd2UgaGF2ZSBpdC4uLiBsb29rcyBsaWtlIGFuIGBtdHJ5YCBvZiAxNyBhbmQgYG1pbl9uYCBvZiA0IGhhZCB0aGUgYmVzdCBgcm1zZWAgdmFsdWUuIFlvdSBjYW4gdmVyaWZ5IHRoaXMgaW4gdGhlIGFib3ZlIG91dHB1dCwgYnV0IGl0IGlzIGVhc2llciB0byBqdXN0IHB1bGwgdGhpcyByb3cgb3V0IHVzaW5nIHRoaXMgZnVuY3Rpb24uIFdlIGNhbiBzZWUgdGhhdCB0aGUgbWVhbiBgcm1zZWAgdmFsdWUgYWNyb3NzIHRoZSBjcm9zcyB2YWxpZGF0aW9uIHNldHMgd2FzIDEuNzEyLiBCZWZvcmUgdHVuaW5nIGl0IHdhcyAxLjcyNSAgd2l0aCBhIHNpbWlsYXIgYHN0ZF9lcnJgIHNvIHRoZSBwZXJmb3JtYW5jZSB3YXMgdmVyeSBzbGlnaHRseSBpbXByb3ZlZC4NCg0KDQojIyAqKkZpbmFsIG1vZGVsIHBlcmZvcm1hbmNlIGV2YWx1YXRpb24qKg0KKioqDQoNCk5vdyB0aGF0IHdlIGhhdmUgZGVjaWRlZCB0aGF0IHdlIGhhdmUgcmVhc29uYWJsZSBwZXJmb3JtYW5jZSB3aXRoIG91ciB0cmFpbmluZyBkYXRhLCB3ZSBjYW4gc3RvcCBidWlsZGluZyBvdXIgbW9kZWwgYW5kIGV2YWx1YXRlIHBlcmZvcm1hbmNlIHdpdGggb3VyIHRlc3RpbmcgZGF0YS4gDQoNCkhlcmUsIHdlIHdpbGwgdXNlIHRoZSByYW5kb20gZm9yZXN0IG1vZGVsIHRoYXQgd2UgYnVpbHQgdG8gcHJlZGljdCB2YWx1ZXMgZm9yIHRoZSBtb25pdG9ycyBpbiB0aGUgdGVzdGluZyBkYXRhIGFuZCB3ZSB3aWxsIHVzZSB0aGUgdmFsdWVzIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgdGhhdCB3ZSBqdXN0IGRldGVybWluZWQgYmFzZWQgb24gb3VyIHR1bmluZyBhbmFseXNpcyB0byBhY2hpZXZlIHRoZSBiZXN0IHBlcmZvcm1hbmNlLg0KDQpTbywgZmlyc3Qgd2UgbmVlZCB0byBzcGVjaWZ5IHRoZXNlIHZhbHVlcyBpbiBhIHdvcmtmbG93LiBXZSBjYW4gdXNlIHRoZSBgc2VsZWN0X2Jlc3QoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIHRvIGdyYWIgdGhlIHZhbHVlcyB0aGF0IHdlcmUgZGV0ZXJtaW5lZCB0byBiZSBiZXN0IGZvciBgbXRyeWAgYW5kIGBtaW5fbmAuDQoNCg0KDQpgYGB7cn0NCg0KdHVuZWRfUkZfdmFsdWVzPC0gc2VsZWN0X2Jlc3QodHVuZV9SRl9yZXN1bHRzLCAicm1zZSIpDQp0dW5lZF9SRl92YWx1ZXMNCmBgYA0KDQpOb3cgd2UgY2FuIGZpbmFsaXplIHRoZSBtb2RlbC93b3JrZmxvdyB0aGF0IHdlIHdlIHVzZWQgZm9yIHR1bmluZyB3aXRoIHRoZXNlIHZhbHVlcy4NCg0KDQpgYGB7cn0NClJGX3R1bmVkX3dmbG93IDwtUkZfdHVuZV93ZmxvdyAlPiUNCiAgdHVuZTo6ZmluYWxpemVfd29ya2Zsb3codHVuZWRfUkZfdmFsdWVzKQ0KYGBgDQoNCg0KV2l0aCB0aGUgYHdvcmtmbG93c2AgcGFja2FnZSwgd2UgY2FuIHVzZSB0aGUgc3BsaXR0aW5nIGluZm9ybWF0aW9uIGZvciBvdXIgb3JpZ2luYWwgZGF0YSBgcG1fc3BsaXRgIHRvIGZpdCB0aGUgZmluYWwgbW9kZWwgb24gdGhlIGZ1bGwgdHJhaW5pbmcgc2V0IGFuZCBhbHNvIG9uIHRoZSB0ZXN0aW5nIGRhdGEgdXNpbmcgdGhlIGBsYXN0X2ZpdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UuIE5vIHByZS1wcm9jZXNzaW5nIHN0ZXBzIGFyZSByZXF1aXJlZC4NCg0KVGhlIHJlc3VsdHMgd2lsbCBzaG93IHRoZSBwZXJmb3JtYW5jZSB1c2luZyB0aGUgdGVzdGluZyBkYXRhLg0KDQoNCmBgYHtyfQ0Kb3ZlcmFsbGZpdCA8LXR1bmU6Omxhc3RfZml0KFJGX3R1bmVkX3dmbG93LCBwbV9zcGxpdCkNCiAjIG9yDQpvdmVyYWxsZml0IDwtUkZfd2Zsb3cgJT4lDQogIHR1bmU6Omxhc3RfZml0KHBtX3NwbGl0KQ0KYGBgDQoNClRoZSBgb3ZlcmFsbGZpdGAgb3V0cHV0IGhhcyBhIGxvdCBvZiByZWFsbHkgdXNlZnVsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBtb2RlbCwgdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIGRhdGEgc3BsaXQsIGFuZCB0aGUgcHJlZGljdGlvbnMgZm9yIHRoZSB0ZXN0aW5nIGRhdGEuDQoNClRvIHNlZSB0aGUgcGVyZm9ybWFuY2Ugb24gdGhlIHRlc3QgZGF0YSB3ZSBjYW4gdXNlIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIGxpa2Ugd2UgZGlkIGJlZm9yZS4NCmBgYHtyfQ0KICBjb2xsZWN0X21ldHJpY3Mob3ZlcmFsbGZpdCkNCiANCmBgYA0KDQpBd2Vzb21lISBXZSBjYW4gc2VlIHRoYXQgb3VyIHJtc2Ugb2YgMS40NCBpcyBxdWl0ZSBzaW1pbGFyIHdpdGggb3VyIHRlc3RpbmcgZGF0YSBjcm9zcyB2YWxpZGF0aW9uIHNldHMuIFdlIGFjaGlldmVkIHF1aXRlIGdvb2QgcGVyZm9ybWFuY2UsIHdoaWNoIHN1Z2dlc3RzIHRoYXQgd2UgY291bGQgcHJlZGljdCBvdGhlciBsb2NhdGlvbnMgd2l0aCBtb3JlIHNwYXJzZSBtb25pdG9yaW5nIGJhc2VkIG9uIG91ciBwcmVkaWN0b3JzIHdpdGggcmVhc29uYWJsZSBhY2N1cmFjeS4NCg0KTm93IGlmIHlvdSB3YW50ZWQgdG8gdGFrZSBhIGxvb2sgYXQgdGhlIHByZWRpY3RlZCB2YWx1ZXMgZm9yIHRoZSB0ZXN0IHNldCAodGhlIDI5MiByb3dzIHdpdGggcHJlZGljdGlvbnMgb3V0IG9mIHRoZSA4NzYgb3JpZ2luYWwgbW9uaXRvciB2YWx1ZXMpIHlvdSBjYW4gdXNlIHRoZSAgYGNvbGxlY3RfcHJlZGljdGlvbnMoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlOg0KDQpgYGB7cn0NCnRlc3RfcHJlZGljdGlvbnMgPC1jb2xsZWN0X3ByZWRpY3Rpb25zKG92ZXJhbGxmaXQpDQpgYGANCg0KYGBge3IsIGV2YWwgPSBGQUxTRX0NCnRlc3RfcHJlZGljdGlvbnMNCmBgYA0KDQojIyMjIHsuc2Nyb2xsYWJsZSB9DQpgYGB7ciwgZWNobyA9RkFMU0V9DQp0ZXN0X3ByZWRpY3Rpb25zICU+JQ0KICBwcmludChuID0gMWUzKQ0KYGBgDQoNCiMjIyMNCg0KTmljZSENCg0KIyMgKipFeGVyY2lzZSoqDQoqKioNCg0KPCEtLS1BUF9EQV9RdWl6LS0+DQoNCjxpZnJhbWUgc3R5bGU9Im1hcmdpbjowIGF1dG87IG1pbi13aWR0aDogMTAwJTsiIGlkPSJBUF9EQV9RdWl6SWZyYW1lIiBjbGFzcz0iaW50ZXJhY3RpdmUiIHNyYz0iaHR0cHM6Ly9yc2Nvbm5lY3QuYmlvc3RhdC5qaHNwaC5lZHUvT0NTX0FQX0RBX1F1aXovIiBzY3JvbGxpbmc9Im5vIiBmcmFtZWJvcmRlcj0ibm8iPjwvaWZyYW1lPg0KDQo8IS0tLS0tLS0tLS0tLS0tLS0+DQoNCiMgKipEYXRhIFZpc3VhbGl6YXRpb24qKg0KKioqDQoNCk91ciBtYWluIHF1ZXN0aW9uIGZvciB0aGlzIGNhc2Ugc3R1ZHkgd2FzOiAgDQoNCj4gQ2FuIHdlIHByZWRpY3QgYW5udWFsIGF2ZXJhZ2UgYWlyIHBvbGx1dGlvbiBjb25jZW50cmF0aW9ucyBhdCB0aGUgZ3JhbnVsYXJpdHkgb2YgemlwIGNvZGUgcmVnaW9uYWwgbGV2ZWxzIHVzaW5nIHByZWRpY3RvcnMgc3VjaCBhcyBkYXRhIGFib3V0IHBvcHVsYXRpb24gZGVuc2l0eSwgdXJiYW5pemF0aW9uLCByb2FkIGRlbnNpdHksIGFzIHdlbGwgYXMsIHNhdGVsbGl0ZSBwb2xsdXRpb24gZGF0YSBhbmQgY2hlbWljYWwgbW9kZWxpbmcgZGF0YT8NCg0KVGh1cyBmYXIsIHdlIGhhdmUgYnVpbHQgYSBtYWNoaW5lIGxlYXJuaW5nIChNTCkgbW9kZWwgdG8gcHJlZGljdCBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciBhaXIgcG9sbHV0aW9uIGxldmVscyBiYXNlZCBvbiBvdXIgcHJlZGljdG9yIHZhcmlhYmxlcyAob3IgZmVhdHVyZXMpLg0KDQpOb3csIGxldCdzIG1ha2UgYSBwbG90IG9mIG91ciBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMgKCRcaGF0e1l9JCkgYW5kIGFjdHVhbCBvdXRjb21lIHZhbHVlcyAkWSQgd2Ugb2JzZXJ2ZWQuIA0KDQpGaXJzdCwgbGV0J3Mgc3RhcnQgYnkgbWFraW5nIGEgcGxvdCBvZiBvdXIgbW9uaXRvcnMuIA0KVG8gZG8gdGhpcywgd2Ugd2lsbCB1c2UgdGhlIGZvbGxvd2luZyBwYWNrYWdlcyB0byBjcmVhdGUgYSBtYXAgb2YgdGhlIFVTOg0KDQoxLiBgc2ZgIC0gdGhlIHNpbXBsZSBmZWF0dXJlcyBwYWNrYWdlIGhlbHBzIHRvIGNvbnZlcnQgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGludG8gYGdlb21ldHJ5YCB2YXJpYWJsZXMgd2hpY2ggYXJlIHVzZWZ1bCBmb3IgbWFraW5nIDJEIHBsb3RzDQoyLiBgbWFwc2AgLSB0aGlzIHBhY2thZ2UgY29udGFpbnMgZ2VvZ3JhcGhpY2FsIG91dGxpbmVzIGFuZCBwbG90dGluZyBmdW5jdGlvbnMgdG8gY3JlYXRlIHBsb3RzIHdpdGggbWFwcyANCjMuIGBybmF0dXJhbGVhcnRoYC0gdGhpcyBhbGxvd3MgZm9yIGVhc3kgaW50ZXJhY3Rpb24gd2l0aCBtYXAgZGF0YSBmcm9tIFtOYXR1cmFsIEVhcnRoXShodHRwOi8vd3d3Lm5hdHVyYWxlYXJ0aGRhdGEuY29tLykgd2hpY2ggaXMgYSBwdWJsaWMgZG9tYWluIG1hcCBkYXRhc2V0DQo0LiBgcmdlb3NgIC0gdGhpcyBwYWNrYWdlIGludGVyZmFjZXMgd2l0aCB0aGUgR2VvbWV0cnkgRW5naW5lLU9wZW4gU291cmNlIChgR0VPU2ApIHdoaWNoIGlzIGFsc28gaGVscGZ1bCBmb3IgY29vcmRpbmF0ZSBjb252ZXJzaW9uDQoNCldlIHdpbGwgc3RhcnQgd2l0aCBnZXR0aW5nIGFuIG91dGxpbmUgb2YgdGhlIFVTIHdpdGggdGhlIGBuZV9jb3VudHJpZXMoKWAgZnVuY3Rpb24gb2YgdGhlIGBybmF0dXJhbGVhcnRoYCBwYWNrYWdlIHdoaWNoIHdpbGwgcmV0dXJuIHBvbHlnb25zIG9mIHRoZSBjb3VudHJpZXMgaW4gdGhlIFtOYXR1cmFsIEVhcnRoXShodHRwOi8vd3d3Lm5hdHVyYWxlYXJ0aGRhdGEuY29tLykgZGF0YXNldC4NCg0KYGBge3J9DQoNCndvcmxkIDwtIG5lX2NvdW50cmllcyhzY2FsZSA9ICJtZWRpdW0iLCByZXR1cm5jbGFzcyA9ICJzZiIpDQpnbGltcHNlKHdvcmxkKQ0KDQpgYGANCg0KDQpIZXJlIHlvdSBjYW4gc2VlIHRoZSBkYXRhIGFib3V0IHRoZSBjb3VudHJpZXMgaW4gdGhlIHdvcmxkLiBOb3RpY2UgdGhlIGBnZW9tZXRyeWAgdmFyaWFibGUuIFRoaXMgaXMgdXNlZCB0byBjcmVhdGUgdGhlIG91dGxpbmVzIHRoYXQgd2Ugd2FudC4gDQoNCk5vdyB3ZSBjYW4gdXNlIHRoZSBgZ2VvbV9zZigpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UgdG8gY3JlYXRlIGEgdmlzdWFsIG9mIHNpbXBsZSBmZWF0dXJlICh0aGUgZ2VvbWV0cnkgY29vcmRpbmF0ZXMgZm91bmQgaW4gdGhlIGBnZW9tZXRyeWAgdmFyaWFibGUpLg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gd29ybGQpICsNCiAgICBnZW9tX3NmKCkgDQoNCmBgYA0KDQpTbyBub3cgd2UgY2FuIHNlZSB0aGF0IHdlIGhhdmUgb3V0bGluZXMgb2YgYWxsIHRoZSBjb3VudHJpZXMgaW4gdGhlIHdvcmxkLg0KDQpXZSB3YW50IHRvIGxpbWl0IHRoaXMganVzdCB0byB0aGUgY29vcmRpbmF0ZXMgZm9yIHRoZSBVUy4gV2Ugd2lsbCBkbyB0aGlzIGJhc2VkIG9uIHRoZSBjb29yZGluYXRlcyB3ZSBmb3VuZCBvbiBXaWtpcGVkaWEuIEFjY29yZGluZyB0byB0aGlzIFtsaW5rXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaXN0X29mX2V4dHJlbWVfcG9pbnRzX29mX3RoZV9Vbml0ZWRfU3RhdGVzI1dlc3Rlcm5tb3N0KXt0YXJnZXQ9Il9ibGFuayJ9LCB0aGVzZSBhcmUgdGhlIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgYm91bmRzIG9mIHRoZSBjb250aW5lbnRhbCBVUzoNCg0KLSB0b3AgPSA0OS4zNDU3ODY4ICMgbm9ydGggbGF0DQotIGxlZnQgPSAtMTI0Ljc4NDQwNzkgIyB3ZXN0IGxvbmcNCi0gcmlnaHQgPSAtNjYuOTUxMzgxMiAjIGVhc3QgbG9uZw0KLSBib3R0b20gPSAgMjQuNzQzMzE5NSAjIHNvdXRoIGxhdA0KDQpgYGB7cn0NCg0KZ2dwbG90KGRhdGEgPSB3b3JsZCkgKw0KICAgIGdlb21fc2YoKSArDQogICAgY29vcmRfc2YoeGxpbSA9IGMoLTEyNSwgLTY2KSwgeWxpbSA9IGMoMjQuNSwgNTApLCANCiAgICAgICAgICAgICBleHBhbmQgPSBGQUxTRSkNCmBgYA0KTm93IHdlIGp1c3QgaGF2ZSBhIHBsb3QgdGhhdCBpcyBtb3N0bHkgbGltaXRlZCB0byB0aGUgb3V0bGluZSBvZiB0aGUgVVMuDQoNCk5vdyB3ZSB3aWxsIHVzZSB0aGUgYGdlb21fcG9pbnQoKWAgZnVuY3Rpb24gb2YgdGhlIGBnZ3Bsb3RgIHBhY2thZ2UgdG8gYWRkIHNjYXR0ZXIgcGxvdCBvbiB0b3Agb2YgdGhlIG1hcC4gV2Ugd2FudCB0byBzaG93IHdoZXJlIHRoZSBtb25pdG9ycyBhcmUgbG9jYXRlZCBiYXNlZCBvbiB0aGUgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSB2YWx1ZXMgaW4gdGhlIGRhdGEuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSB3b3JsZCkgKw0KICAgIGdlb21fc2YoKSArDQogICAgY29vcmRfc2YoeGxpbSA9IGMoLTEyNSwgLTY2KSwgeWxpbSA9IGMoMjQuNSwgNTApLCANCiAgICAgICAgICAgICBleHBhbmQgPSBGQUxTRSkrDQogICAgZ2VvbV9wb2ludChkYXRhID0gcG0sIGFlcyh4ID0gbG9uLCB5ID0gbGF0KSwgc2l6ZSA9IDIsIA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMywgZmlsbCA9ICJkYXJrcmVkIikNCg0KYGBgDQpOaWNlIQ0KDQpOb3cgbGV0J3MgYWRkIGNvdW50eSBsaW5lcy4NCg0KQ291bnR5IGdyYXBoaWNhbCBkYXRhIGlzIGF2YWlsYWJsZSBmcm9tIHRoZSBgbWFwc2AgcGFja2FnZS4gDQpUaGUgYHNmYCBwYWNrYWdlIHdoaWNoIGFnYWluIGlzIHNob3J0IGZvciBzaW1wbGUgZmVhdHVyZXMgY3JlYXRlcyBhIGRhdGEgZnJhbWUgYWJvdXQgdGhpcyBncmFwaGljYWwgZGF0YSBzbyB0aGF0IHdlIGNhbiB3b3JrIHdpdGggaXQuDQoNCmBgYHtyfQ0KY291bnRpZXMgPC0gDQogIHNmOjpzdF9hc19zZihtYXBzOjptYXAoImNvdW50eSIsIHBsb3QgPSBGQUxTRSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IFRSVUUpKQ0KDQpjb3VudGllcw0KYGBgDQoNCk5vdyB3ZSB3aWxsIHVzZSB0aGlzIGRhdGEgd2l0aGluIHRoZSBgZ2VvbV9zZigpYCBmdW5jdGlvbiB0byBhZGQgdGhpcyB0byBvdXIgcGxvdC4gIFdlIHdpbGwgYWxzbyBhZGQgYSB0aXRsZSB1c2luZyB0aGUgYGdndGl0bGUoKWAgZnVuY3Rpb24sIGFzIHdlbGwgYXMgcmVtb3ZlIGF4aXMgdGlja3MgYW5kIHRpdGxlcyB1c2luZyB0aGUgYHRoZW1lKClgIGZ1bmN0aW9uIG9mIHRoZSBgZ2dwbG90MmAgcGFja2FnZS4NCg0KYGBge3J9DQptb25pdG9ycyA8LSBnZ3Bsb3QoZGF0YSA9IHdvcmxkKSArDQogICAgZ2VvbV9zZihkYXRhID0gY291bnRpZXMsIGZpbGwgPSBOQSwgY29sb3IgPSBncmF5KC41KSkrDQogICAgICBjb29yZF9zZih4bGltID0gYygtMTI1LCAtNjYpLCB5bGltID0gYygyNC41LCA1MCksIA0KICAgICAgICAgICAgIGV4cGFuZCA9IEZBTFNFKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gcG0sIGFlcyh4ID0gbG9uLCB5ID0gbGF0KSwgc2l6ZSA9IDIsIA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMywgZmlsbCA9ICJkYXJrcmVkIikgKw0KICAgIGdndGl0bGUoIk1vbml0b3IgTG9jYXRpb25zIikgKw0KICAgIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKQ0KDQptb25pdG9ycw0KYGBgDQoNCkdyZWF0IQ0KDQpOb3csIGxldCdzIGFkZCBhIGZpbGwgYXQgdGhlIGNvdW50eS1sZXZlbCBmb3IgdGhlIHRydWUgbW9uaXRvciB2YWx1ZXMgb2YgYWlyIHBvbGx1dGlvbi4NCg0KRmlyc3QsIHdlIG5lZWQgdG8gZ2V0IHRoZSBjb3VudHkgbWFwIGRhdGEgdGhhdCB3ZSBqdXN0IGdvdCBhbmQgb3VyIGFpciBwb2xsdXRpb24gZGF0YSB0byBoYXZlIHNpbWlsYXJseSBmb3JtYXR0ZWQgY291bnR5IG5hbWVzIHNvIHRoYXQgd2UgY2FuIGNvbWJpbmUgdGhlIGRhdGFzZXRzIHRvZ2V0aGVyLg0KDQpXZSBjYW4gc2VlIHRoYXQgaW4gdGhlIGBjb3VudHlgIGRhdGEgdGhlIGNvdW50aWVzIGFyZSBsaXN0ZWQgYWZ0ZXIgdGhlIHN0YXRlIG5hbWUgYW5kIGEgY29tbWEuIEluIGFkZGl0aW9uIHRoZXkgYXJlIGFsbCBsb3dlciBjYXNlLg0KDQoNCmBgYHtyfQ0KaGVhZChjb3VudGllcykNCmBgYA0KDQpJbiBjb250cmFzdCwgb3VyIGFpciBwb2xsdXRpb24gYHBtYCBkYXRhIHNob3dzIGNvdW50aWVzIGFzIHRpdGxlcyB3aXRoIHRoZSBmaXJzdCBsZXR0ZXIgYXMgdXBwZXIgY2FzZS4gDQoNCmBgYHtyfQ0KZHBseXI6OnB1bGwocG0sIGNvdW50eSkgJT4lDQogIGhlYWQoKQ0KYGBgDQoNCldlIGNhbiB1c2UgdGhlIGBzZXBhcmF0ZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlIHRvIHNlcGFyYXRlIHRoZSBgSURgIHZhcmlhYmxlIG9mIG91ciBgY291bnRpZXNgIGRhdGEgaW50byB0d28gYHZhcmlhYmxlc2AgYmFzZWQgb24gdGhlIGNvbW1hIGFzIGEgc2VwYXJhdG9yLg0KDQpgYGB7cn0NCmNvdW50aWVzICU8PiUgDQogIHRpZHlyOjpzZXBhcmF0ZShJRCwgaW50byA9IGMoInN0YXRlIiwgImNvdW50eSIpLCBzZXAgPSAiLCIpDQoNCmhlYWQoY291bnRpZXMpDQpgYGANCk5vdyB3ZSBqdXN0IG5lZWQgdG8gbWFrZSB0aGVzZSBuYW1lcyBpbiB0aGUgbmV3IGBjb3VudHlgIHZhcmlhYmxlIG9mIHRoZSBgY291bnRpZXNgIGRhdGEgdG8gYmUgaW4gdGl0bGUgZm9ybWF0LiBXZSBjYW4gdXNlIHRoZSBgc3RyX3RvX3RpdGxlKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZSB0byBkbyB0aGlzLiANCmBgYHtyfQ0KY291bnRpZXNbWyJjb3VudHkiXV0gPC0gc3RyaW5ncjo6c3RyX3RvX3RpdGxlKGNvdW50aWVzW1siY291bnR5Il1dKQ0KYGBgDQoNCkdyZWF0ISBOb3cgdGhlIGNvdW50eSBpbmZvcm1hdGlvbiBpcyB0aGUgc2FtZSBmb3IgdGhlIGBjb3VudGllc2AgYW5kIGBwbWAgZGF0YS4NCg0KV2UgY2FuIHVzZSB0aGUgYGlubmVyX2pvaW4oKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byBqb2luIHRoZSBkYXRhc2V0cyB0b2dldGhlciBiYXNlZCBvbiB0aGUgYGNvdW50eWAgdmFyaWFibGVzIGluIGVhY2guIFRoaXMgZnVuY3Rpb24gd2lsbCBrZWVwIGFsbCByb3dzIHRoYXQgYXJlIGluIGJvdGggZGF0YXNldHMuDQoNCmBgYHtyfQ0KbWFwX2RhdGEgPC1kcGx5cjo6aW5uZXJfam9pbihjb3VudGllcywgcG0sIGJ5ID0gImNvdW50eSIpDQoNCmdsaW1wc2UobWFwX2RhdGEpDQoNCmBgYA0KTmljZSEgd2UgY2FuIHNlZSB0aGF0IHdlIGhhdmUgYWRkIGEgYGdlb21gIHZhcmlhYmxlIHRvIHRoZSBgcG1gIGRhdGEuDQoNCk5vdyB3ZSBjYW4gdXNlIHRoaXMgdG8gY29sb3IgdGhlIGNvdW50aWVzIGluIG91ciBwbG90IGJhc2VkIG9uIHRoZSBgdmFsdWVgIHZhcmlhYmxlIG9mIG91ciBgcG1gIGRhdGEsIHdoaWNoIHlvdSBtYXkgcmVjYWxsIGlzIHRoZSBhY3R1YWwgbW9uaXRvciBkYXRhIGZvciBmaW5lIHBhcnRpY3VsYXRlIGFpciBwb2xsdXRpb24gYXQgZWFjaCBtb25pdG9yLiANCg0KV0UgY2FuIGRvIHNvIHVzaW5nIHRoZSBgc2NhbGVfZmlsbF9ncmFkaWVudG4oKWAgZnVuY3Rpb24gb2YgdGhlIGBnZ3Bsb3QyYCBwYWNrYWdlIHdoaWNoIGNyZWF0ZXMgY29sb3IgZ3JhZGllbnQgYmFzZWQgb24gYSB2YXJpYWJsZS4gSW4gdGhpcyBjYXNlIGl0IGlzIHRoZSB2YXJpYWJsZSB0aGF0IHdhcyBzcGVjaWZpZWQgYXMgdGhlIGBmaWxsYCBpbiB0aGUgYGFlc2AgZnVuY3Rpb24gb2YgdGhlIGBnZW9tX3NmKClgIGZ1bmN0aW9uLiBXZSBzcGVjaWZpZWQgdGhhdCBpdCB3b3VsZCBiZSB0aGUgYHZhbHVlYCB2YXJpYWJsZSBvZiB0aGUgYHBtYCBkYXRhLg0KDQpUaGlzIGBzY2FsZV9maWxsX2dyYWRpZW50bigpYCBmdW5jdGlvbiAgYWxzbyBhbGxvd3MgeW91IHRvIHNwZWNpZnkgdGhlIGNvbG9ycywgd2hhdCB0byBkbyBhYm91dCBOQSB2YWx1ZXMgKHNob3VsZCB0aGV5IGJlIGEgc3BlY2lmaWMgY29sb3Igb3IgdHJhbnNwYXJlbnQpIGFuZCB0aGUgYnJlYWtzLCBsaW1pdHMsIGxhYmVscyBhbmQgbmFtZS90aXRsZSBvbiB0aGUgbGVnZW5kIGZvciB0aGUgY29sb3IgZ3JhZGllbnQuIA0KDQpgYGB7cn0NCg0KdHJ1dGggPC1nZ3Bsb3QoZGF0YSA9IHdvcmxkKSArDQogIGNvb3JkX3NmKHhsaW0gPSBjKC0xMjUsIC02NiksIHlsaW0gPSBjKDI0LjUsIDUwKSwgZXhwYW5kID0gRkFMU0UpKw0KICAgIGdlb21fc2YoZGF0YSA9IG1hcF9kYXRhLCBhZXMoZmlsbCA9IHZhbHVlKSkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPXRvcG8uY29sb3JzKDcpLCBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3M9YygwLDEwLDIwKSxsYWJlbHM9YygwLDEwLDIwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cz1jKDAsMjMuNSksIG5hbWUgPSAiUE0gdWcvbTMiKSArDQogIGdndGl0bGUoIlRydWUgUE0gMi41IGxldmVscyIpICsNCiAgICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkNCg0KdHJ1dGgNCg0KYGBgDQpOaWNlIQ0KDQpOb3cgbGV0J3MgZG8gdGhlIHNhbWUgd2l0aCBvdXIgcHJlZGljdGVkIG91dGNvbWUgdmFsdWVzLg0KDQpMZXQncyBncmFiIGJvdGggdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIHByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyBzbyB0aGF0IHdlIGhhdmUgYXMgbXVjaCBkYXRhIGFzIHBvc3NpYmxlLiANCg0KRmlyc3Qgd2UgbmVlZCB0byBmaXQgb3VyIHRyYWluaW5nIGRhdGEgd2l0aCBvdXIgZmluYWwgbW9kZWwgdG8gYmUgYWJsZSB0byBnZXQgdGhlIHByZWRpY3Rpb25zIGZvciB0aGUgbW9uaXRvcnMgaW5jbHVkZWQgaW4gdGhlIHRyYWluaW5nIHNldC4gV2UgZGlkIHRoaXMgdXNpbmcgdGhlIGBsYXN0X2ZpdCgpYCBmdW5jdGlvbiwgYnV0IHRoZSBvdXRwdXQgb2YgdGhpcyBtYWtlcyBpdCBkaWZmaWN1bHQgdG8gZ3JhYiB0aGUgcHJlZGljdGVkIHZhbHVlcyBmb3IgdGhlIHRyYWluaW5nIGRhdGEsIGFuZCBpdCBpcyBhbHNvIGRpZmZpY3VsdCB0byBnZXQgdGhlIGlkIHZhcmlhYmxlcyBmb3IgdGhlIHRlc3RpbmcgZGF0YS4gDQoNCg0KVGh1cyB3ZSB3aWxsIHVzZSB0aGUgcGFyc25pcCBgZml0KClgIGFuZCBgcHJlZGljdCgpYCBmdW5jdGlvbnMgb2YgdGhlIGBwYXJzbmlwYCBwYWNrYWdlIHRvIGRvIHRoaXMgbGlrZSBzbzoNCg0KIyMjIyB7LnRoaW5rX3F1ZXN0aW9uX2Jsb2NrfQ0KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+DQoNCldoeSBkbyB3ZSBub3QgbmVlZCBwcmUtcHJvY2Vzc2VkIGRhdGE/DQoNCiMjIyMNCg0KKioqDQoNCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGFuc3dlci4gPC9zdW1tYXJ5Pg0KDQpTaW5jZSB3ZSBhcmUgdXNpbmcgYSB3b3JrZmxvdywgdGhlIGRhdGEgd2lsbCBiZSBwcmUtcHJvY2Vzc2VkIHdoZW4gaXQgaXMgZml0IGFzIHdlbGwuDQoNCjwvZGV0YWlscz4NCioqKg0KDQoNCmBgYHtyfQ0KDQpSRl9maW5hbF90cmFpbl9maXQgPC0gcGFyc25pcDo6Zml0KFJGX3R1bmVkX3dmbG93LCBkYXRhID0gdHJhaW5fcG0pDQpSRl9maW5hbF90ZXN0X2ZpdCA8LSBwYXJzbmlwOjpmaXQoUkZfdHVuZWRfd2Zsb3csIGRhdGEgPSB0ZXN0X3BtKQ0KDQoNCnZhbHVlc19wcmVkX3RyYWluIDwtIA0KICBwcmVkaWN0KFJGX2ZpbmFsX3RyYWluX2ZpdCwgdHJhaW5fcG0pICU+JSANCiAgYmluZF9jb2xzKHRyYWluX3BtICU+JSBzZWxlY3QodmFsdWUsIGZpcHMsIGNvdW50eSwgaWQpKSANCg0KdmFsdWVzX3ByZWRfdHJhaW4NCg0KdmFsdWVzX3ByZWRfdGVzdCA8LSANCiAgcHJlZGljdChSRl9maW5hbF90ZXN0X2ZpdCwgdGVzdF9wbSkgJT4lIA0KICBiaW5kX2NvbHModGVzdF9wbSAlPiUgc2VsZWN0KHZhbHVlLCBmaXBzLCBjb3VudHksIGlkKSkgDQoNCnZhbHVlc19wcmVkX3Rlc3QNCmBgYA0KDQpOb3cgd2UgY2FuIGNvbWJpbmUgdGhpcyBkYXRhIGZvciB0aGUgcHJlZGljdGlvbnMgZm9yIGFsbCBtb25pdG9ycyB1c2luZyB0aGUgYGJpbmRfcm93cygpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLCB3aGljaCB3aWxsIGVzc2VudGlhbGx5IGFwcGVuZCB0aGUgc2Vjb25kIGRhdGFzZXQgdG8gdGhlIGZpcnN0Lg0KDQpgYGB7cn0NCmFsbF9wcmVkIDwtIGJpbmRfcm93cyh2YWx1ZXNfcHJlZF90ZXN0LCB2YWx1ZXNfcHJlZF90cmFpbikNCg0KYWxsX3ByZWQNCmBgYA0KDQpHcmVhdCEgYXMgd2UgY2FuIHNlZSB0aGVyZSBhcmUgODc2IHZhbHVlcyBsaWtlIHdlIHdvdWxkIGV4cGVjdCBmb3IgYWxsIG9mIHRoZSBtb25pdG9ycy4gV2UgY2FuIHVzZSB0aGUgYGNvdW50eWAgdmFyaWFibGUgdG8gY29tYmluZSB0aGlzIHdpdGggdGhlIGBjb3VudGllc2AgZGF0YSBsaWtlIHdlIGRpZCB3aXRoIHRoZSBgcG1gIGRhdGEgcHJldmlvdXNseSBzbyB0aGF0IHdlIGNhbiB1c2UgdGhlIGB2YWx1ZWAgdmFyaWFibGUgYXMgYSBjb2xvciBzY2hlbWUgZm9yIG91ciBtYXAuDQoNCg0KYGBge3J9DQptYXBfZGF0YSA8LSBpbm5lcl9qb2luKGNvdW50aWVzLCBhbGxfcHJlZCwgYnkgPSAiY291bnR5IikNCg0KcHJlZCA8LSBnZ3Bsb3QoZGF0YSA9IHdvcmxkKSArDQogICAgICAgICAgY29vcmRfc2YoeGxpbSA9IGMoLTEyNSwgLTY2KSwgeWxpbSA9IGMoMjQuNSwgNTApLCANCiAgICAgICAgICAgICAgICAgZXhwYW5kID0gRkFMU0UpICsNCiAgICBnZW9tX3NmKGRhdGEgPSBtYXBfZGF0YSwgYWVzKGZpbGwgPSAucHJlZCkpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz10b3BvLmNvbG9ycyg3KSwgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICBicmVha3M9YygwLDEwLDIwKSxsYWJlbHM9YygwLDEwLDIwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwyMy41KSwgbmFtZSA9ICJQTSB1Zy9tMyIpICsNCiAgZ2d0aXRsZSgiUHJlZGljdGVkIFBNIDIuNSBsZXZlbHMiKSsNCiAgICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkNCg0KcHJlZA0KYGBgDQoNCk5vdyB3ZSB3aWxsIHVzZSB0aGUgYHBhdGNod29ya2AgcGFja2FnZSB0byBjb21iaW5lIG91ciBsYXN0IHR3byBwbG90cy4gVGhpcyBhbGxvd3MgdXMgdG8gY29tYmluZSBwbG90cyB1c2luZyB0aGUgYCtgIG9yIHRoZSBgL2AgLiBUaGUgYCtgIHdpbGwgcGxhY2UgcGxvdHMgc2lkZSBieSBzaWRlIGFuZCB0aGUgYC9gIHdpbGwgcGxhY2UgcGxvdHMgdG9wIHRvIGJvdHRvbS4NCg0KDQpOb3cgbGV0J3MganVzdCBjb21iaW5lIHRoZSB0cnV0aCBwbG90IGFuZCB0aGUgcHJlZGljdGlvbiBwbG90cyB0b2dldGhlcjoNCmBgYHtyfQ0KdHJ1dGgvcHJlZA0KDQpgYGANCg0KV2UgY2FuIHNlZSB0aGF0IHRoZSBwcmVkaWN0ZWQgZmluZSBwYXJ0aWNsZSBhaXIgcG9sbHV0aW9uIHZhbHVlcyBpbiAodWcvbTMpIGFyZSBxdWl0ZSBzaW1pbGFyIHRvIHRoZSB0cnVlIHZhbHVlcyBtZWFzdXJlZCBieSB0aGUgYWN0dWFsIGdyYXZpbWV0cmljIG1vbml0b3JzLiBXZSBjYW4gYWxzbyBzZWUgdGhhdCBzb3V0aGVybiBDYWxpZm9ybmlhIGhhcyBzb21lIGxhcmdlIGNvdW50aWVzIHdpdGggd29yc2UgcG9sbHV0aW9uIChhcyB0aGV5IGFyZSB5ZWxsb3cgYW5kIHRodXMgaGF2ZSBtdWNoIGhpZ2hlciBwYXJ0aWN1bGF0ZSBtYXR0ZXIgbGV2ZWxzKS4NCg0KTGV0J3MgYWRkIHNvbWUgdGV4dCB0byBvdXIgcGxvdCB0byBleHBsYWluIGl0IGEgYml0IG1vcmUuIFdlIGNhbiBkbyBzbyB1c2luZyB0aGUgYHBsb3RfYW5ub3RhdGlvbigpYCBmdW5jdGlvbiBvZiB0aGUgYHBhdGNod29ya2AgcGFja2FnZS4gVGhlIGB0aGVtZWAgYXJndW1lbnQgb2YgdGhpcyBmdW5jdGlvbiB0YWtlcyB0aGUgc2FtZSB0aGVtZSBpbmZvcm1hdGlvbiB1c2luZyB0aGUgYHRoZW1lKClgIGZ1bmN0aW9uIG9mIHRoZSBgZ2dwbG90MmAgcGFja2FnZSBhcyB3aGVuIGNyZWF0aW5nIGBnZ3Bsb3QyYHBsb3RzLg0KDQpgYGB7cn0NCih0cnV0aC9wcmVkKSArIHBsb3RfYW5ub3RhdGlvbih0aXRsZSA9ICJNYWNoaW5lIExlYXJuaW5nIE1ldGhvZHMgQWxsb3cgZm9yIFByZWRpY3Rpb24gb2YgQWlyIFBvbGx1dGlvbiIsIHN1YnRpdGxlID0gIkEgcmFuZG9tIGZvcmVzdCBtb2RlbCBwcmVkaWN0cyB0cnVlIG1vbml0b3JlZCBsZXZlbHMgb2YgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIgKFBNIDIuNSkgYWlyIHBvbGx1dGlvbiBiYXNlZCBvblxuZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHkgYW5kIG90aGVyIHByZWRpY3RvcnMgcmVhc29uYWJseSB3ZWxsLCB0aHVzIHN1Z2dlc3RpbmcgdGhhdCB3ZSBjYW4gcHJlZGljdCBsZXZlbHNcbm9mIHBvbGx1dGlvbiBpbiBwbGFjZXMgd2l0aCBwb29yIG1vbml0b3JpbmciLCB0aGVtZSA9IHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9MTIsIGZhY2UgPSAiYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkpDQoNCmBgYA0KDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGV2YWw9RkFMU0UsIGluY2x1ZGUgPSBGQUxTRX0NCnBuZyhoZXJlOjpoZXJlKCJpbWciLCAibWFpbl9wbG90X21hcHMucG5nIiksIA0KICAgIGhlaWdodCA9IDE1MDAsIHdpZHRoID0gMjAwMCwgcmVzID0gMzAwKQ0KKHRydXRoL3ByZWQpICsgcGxvdF9hbm5vdGF0aW9uKHRpdGxlID0gIk1hY2hpbmUgTGVhcm5pbmcgTWV0aG9kcyBBbGxvdyBmb3IgUHJlZGljdGlvbiBvZiBBaXIgUG9sbHV0aW9uIiwgc3VidGl0bGUgPSAiQSByYW5kb20gZm9yZXN0IG1vZGVsIHByZWRpY3RzIHRydWUgbW9uaXRvcmVkIGxldmVscyBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciAoUE0gMi41KSBhaXIgcG9sbHV0aW9uIGJhc2VkIG9uXG5kYXRhIGFib3V0IHBvcHVsYXRpb24gZGVuc2l0eSBhbmQgb3RoZXIgcHJlZGljdG9ycyByZWFzb25hYmx5IHdlbGwsIHRodXMgc3VnZ2VzdGluZyB0aGF0IHdlIGNhbiBwcmVkaWN0IGxldmVsc1xub2YgcG9sbHV0aW9uIGluIHBsYWNlcyB3aXRoIHBvb3IgbW9uaXRvcmluZyIsIHRoZW1lID0gdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0xMiwgZmFjZSA9ICJib2xkIiksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSkNCmRldi5vZmYoKQ0KYGBgDQoNCiMgKipTdW1tYXJ5KioNCioqKg0KDQojIyAqKlN5bm9wc2lzKioNCioqKg0KDQpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIGV4cGxvcmVkIGdyYXZpbWV0cmljIG1vbml0b3JpbmcgZGF0YSBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciBhaXIgcG9sbHV0aW9uIChvdXRjb21lIHZhcmlhYmxlKS4gDQpPdXIgZ29hbCB3YXMgdG8gYWJsZSB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gd2hlcmUgd2Ugb25seSBoYWQgcHJlZGljdG9yIHZhcmlhYmxlcyAob3IgZmVhdHVyZXMpIHdpdGhvdXQgaGF2aW5nIG9ic2VydmVkIGEgY29ycmVzcG9uZGluZyBtZWFzdXJlbWVudCBvZiBhaXIgcG9sbHV0aW9uLg0KDQpPdXIgbGVhcm5pbmcgb2JqZWN0aXZlcyB3ZXJlOiANCg0KLSBJbnRyb2R1Y2UgY29uY2VwdHMgaW4gbWFjaGluZSBsZWFybmluZw0KLSBEZW1vbnN0cmF0ZSBob3cgdG8gYnVpbGQgYSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVsIHdpdGggYHRpZHltb2RlbHNgDQotIERlbW9uc3RyYXRlIGhvdyB0byB2aXN1YWxpemUgZ2VvLXNwYXRpYWwgZGF0YSB1c2luZyBgZ2dwbG90MmANCg0KVXNpbmcgdGhlIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWxzIGJ1aWx0IGluIHRoaXMgY2FzZSBzdHVkeSwgd2UgY291bGQgbm93IGV4dGVuZCB0aGlzIG1vZGVsIHRvIGJlIHVzZWQgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyBpbiBhcmVhcyB3aXRoIHBvb3IgbW9uaXRvcmluZywgdG8gaGVscCBpZGVudGlmeSByZWdpb25zIHdoZXJlIHBvcHVsYXRpb25zIG1heWJlIGVzcGVjaWFsbHkgYXQgcmlzayBmb3IgdGhlIGhlYWx0aCBlZmZlY3RzIG9mIGFpciBwb2xsdXRpb24uICANCg0KQW5hbHlzZXMgbGlrZSB0aGUgb25lIGluIG91ciBjYXNlIHN0dWR5IGFyZSBpbXBvcnRhbnQgZm9yIGRlZmluaW5nIHdoaWNoIGdyb3VwcyBjb3VsZCBiZW5lZml0IHRoZSBtb3N0IGZyb20gaW50ZXJ2ZW50aW9ucywgZWR1Y2F0aW9uLCBhbmQgcG9saWN5IGNoYW5nZXMgd2hlbiBhdHRlbXB0aW5nIHRvIG1pdGlnYXRlIHB1YmxpYyBoZWFsdGggY2hhbGxlbmdlcy4gWW91IGNhbiBzZWUgaW4gdGhpcyBbYXJ0aWNsZV0oaHR0cHM6Ly93d3cubmVqbS5vcmcvZG9pL2Z1bGwvMTAuMTA1Ni9ORUpNb2ExNzAyNzQ3KXt0YXJnZXQ9Il9ibGFuayJ9IHRoYXQgbWFueSBhZGRpdGlvbmFsIGNvbnNpZGVyYXRpb25zIHdvdWxkIGJlIGludm9sdmVkIHRvIGFkZXF1YXRlbHkgdW5kZXJzdGFuZCB0aGUgZGF0YSBlbm91Z2ggdG8gcmVjb21tZW5kIHBvbGljeSBjaGFuZ2VzLg0KDQpIZXJlIGFyZSBzb21lIHZpc3VhbCBzdW1tYXJpZXMgYWJvdXQgd2hhdCB3ZSBsZWFybmVkIGFib3V0IHVzaW5nIGB0aWR5bW9kZWxzYCB0byBwZXJmb3JtIHByZWRpY3Rpb24gYW5hbHlzZXMuDQoNCkZpcnN0IHRoZSBtaW5pbWFsIHN0ZXBzIHJlcXVpcmVkOg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJ0aWR5bW9kZWxzQmFzaWNzLnBuZyIpKQ0KYGBgDQoNCg0KSGVyZSBpcyBhIGd1aWRlIGZvciBtb3JlIGFkdmFuY2VkIGFuYWx5c2VzIGludm9sdmluZyBwcmVwcm9jZXNzaW5nLCBjcm9zcyB2YWxpZGF0aW9uLCBvciB0dW5pbmc6DQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsImZ1bGxfdGlkeW1vZGVsc19vdmVydmlldy5wbmciKSkNCmBgYA0KDQoNCg0KDQo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSBmb3IgbW9yZSBvbiB3aGF0IHdlIGxlYXJuZWQgd2l0aCBgdGlkeW1vZGVsc2AgPC9zdW1tYXJ5Pg0KDQpIZXJlLCB3ZSBwcm92aWRlIGFuIG92ZXJ2aWV3IG9mIHRoZSBgdGlkeW1vZGVsc2AgZnJhbWV3b3JrLiANCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiZWNvc3lzdGVtLnBuZyIpKQ0KYGBgDQoNCg0KV2UgcGVyZm9ybWVkIHRoZSBtYWpvciBzdGVwcyBvZiBtYWNoaW5lIGxlYXJuaW5nIHRoYXQgd2UgaW50cm9kdWNlZCBpbiB0aGUgYmVnaW5uaW5nIG9mIHRoZSBkYXRhIGFuYWx5c2lzOiAgDQoNCjEuIERhdGEgZXhwbG9yYXRpb24gIA0KDQpXZSB1c2VkIHBhY2thZ2VzIGxpa2UgYHNraW1yYCwgYHN1bW1hcnl0b29sc2AsIGBjb3JycGxvdGAsIGFuZCBgR0dhbGx5YCB0byBiZXR0ZXIgdW5kZXJzdGFuZCBvdXIgZGF0YS4gVGhlc2UgcGFja2FnZXMgY2FuIHRlbGwgdXMgaG93IG1hbnkgbWlzc2luZyB2YWx1ZXMgZWFjaCB2YXJpYWJsZSBoYXMgKGlmIGFueSksIHRoZSBjbGFzcyBvZiBlYWNoIHZhcmlhYmxlLCB0aGUgZGlzdHJpYnV0aW9uIG9mIHZhbHVlcyBmb3IgZWFjaCB2YXJpYWJsZSwgdGhlIHNwYXJzaXR5IG9mIGVhY2ggdmFyaWFibGUsIGFuZCB0aGUgbGV2ZWwgb2YgY29ycmVsYXRpb24gYmV0d2VlbiB2YXJpYWJsZXMuICANCg0KMi4gRGF0YSBzcGxpdHRpbmcgDQoNCldlIHVzZWQgdGhlIGByc2FtcGxlYCBwYWNrYWdlIHRvIGZpcnN0IHBlcmZvcm0gYW4gaW5pdGlhbCBzcGxpdCBvZiBvdXIgZGF0YSBpbnRvIHR3byBwaWVjZXM6IGEgdHJhaW5pbmcgc2V0IGFuZCBhIHRlc3Rpbmcgc2V0LiBUaGUgdHJhaW5pbmcgc2V0IHdhcyB1c2VkIHRvIG9wdGltaXplIHRoZSBtb2RlbCwgd2hpbGUgdGhlIHRlc3Rpbmcgc2V0IHdhcyB1c2VkIG9ubHkgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIG91ciBmaW5hbCBtb2RlbC4gV2UgYWxzbyB1c2VkIHRoZSBgcnNhbXBsZWAgcGFja2FnZSB0byBjcmVhdGUgY3Jvc3MgdmFsaWRhdGlvbiBzdWJzZXRzIG9mIG91ciB0cmFpbmluZyBkYXRhLiBUaGlzIGFsbG93ZWQgdXMgdG8gYmV0dGVyIGFzc2VzcyB0aGUgcGVyZm9ybWFuY2Ugb2Ygb3VyIHRlc3RlZCBtb2RlbHMgdXNpbmcgb3VyIHRyYWluaW5nIGRhdGEuICANCg0KMy4gVmFyaWFibGUgYXNzaWdubWVudCBhbmQgcHJlLXByb2Nlc3NpbmcgICANCg0KV2UgdXNlZCB0aGUgYHJlY2lwZXNgIHBhY2thZ2UgdG8gYXNzaWduIHZhcmlhYmxlIHJvbGVzIChzdWNoIGFzIG91dGNvbWUsIHByZWRpY3RvciwgYW5kIGlkIHZhcmlhYmxlKS4gV2UgYWxzbyB1c2VkIHRoaXMgcGFja2FnZSB0byBjcmVhdGUgYSByZWNpcGUgZm9yIHByZS1wcm9jZXNzaW5nIG91ciB0cmFpbmluZyBhbmQgdGVzdGluZyBkYXRhLiBUaGlzIGludm9sdmVkIHN0ZXBzIHN1Y2ggYXM6IGAgc3RlcF9kdW1teWAgdG8gY3JlYXRlIGR1bW15IG51bWVyaWMgZW5jb2RpbmdzIG9mIG91ciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMsIGBzdGVwX2NvcnJgIHRvIHJlbW92ZSBoaWdobHkgY29ycmVsYXRlZCB2YXJpYWJsZXMsIGBzdGVwX256dmAgdG8gcmVtb3ZlIG5lYXIgemVybyB2YXJpYW5jZSB2YXJpYWJsZXMgdGhhdCB3b3VsZCBjb250cmlidXRlIGxpdHRsZSB0byBvdXIgbW9kZWwgYW5kIHBvdGVudGlhbGx5IGFkZCBub2lzZS4gIFdlIGxlYXJuZWQgdGhhdCBvbmNlIG91ciByZWNpcGUgd2FzIGNyZWF0ZWQgYW5kIHByZXBwZWQgdXNpbmcgYHByZXAoKWB3ZSBjb3VsZCBleHRyYWN0IHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgb3Igb3VyIHByZS1wcm9jZXNzZWQgdGVzdGluZyBkYXRhIHVzaW5nIGBiYWtlKClgLiBXZSBhbHNvIGxlYXJuZWQgdGhhdCBpZiB3ZSB1c2VkIHRoZSBuZXdlciB3b3JrZmxvd3MgcGFja2FnZSB0aGF0IHdlIGRpZCBub3QgbmVlZCB0byB1c2UgdGhlIGBwcmVwKClgIG9yIGBiYWtlKClgIGZ1bmN0aW9ucywgYnV0IHRoYXQgaXQgaXMgc3RpbGwgdXNlZnVsIHRvIGtub3cgaG93IHRvIGRvIHNvIGlmIHdlIHdhbnQgdG8gbG9vayBhdCBvdXIgZGF0YSBhbmQgaG93IHRoZSByZWNpcGUgaXMgaW5mbHVlbmNpbmcgaXQgbW9yZSBkZWVwbHkuICANCg0KNC4gTW9kZWwgc3BlY2lmaWNhdGlvbiwgZml0dGluZywgdHVuaW5nIGFuZCBwZXJmb3JtYW5jZSBldmFsdWF0aW9uIHVzaW5nIHRoZSB0cmFpbmluZyBkYXRhICANCg0KV2UgbGVhcm5lZCB0aGF0IHRoZSBtb2RlbCBuZWVkcyB0byBmaXJzdCBiZSBmaXQgdG8gdGhlIHRyYWluaW5nIGRhdGEuIFdlIGxlYXJuZWQgdGhhdCBpbiBib3RoIGNsYXNzaWZpY2F0aW9uIGFuZCBwcmVkaWN0aW9uLCB0aGUgbW9kZWwgaXMgZml0IHRvIHRoZSB0cmFpbmluZyBkYXRhIGFuZCB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGFyZSB1c2VkIHRvIGVzdGltYXRlIG51bWVyaWMgdmFsdWVzIChpbiB0aGUgY2FzZSBvZiBwcmVkaWN0aW9uKSBvciBjYXRlZ29yaWNhbCB2YWx1ZXMgKGluIHRoZSBjYXNlIG9mIGNsYXNzaWZpY2F0aW9uKSBvZiB0aGUgb3V0Y29tZSB2YXJpYWJsZSBvZiBpbnRlcmVzdC4gV2UgbGVhcm5lZCB0aGF0IHdlIHNwZWNpZnkgdGhlIG1vZGVsIGFuZCBpdHMgc3BlY2lmaWNhdGlvbnMgdXNpbmcgdGhlIGBwYXJuc2lwYCBwYWNrYWdlIGFuZCB0aGF0IHdlIGFsc28gdXNlIHRoaXMgcGFja2FnZSB0byBmaXQgdGhlIG1vZGVsIHVzaW5nIHRoZSBgZml0KClgIGZ1bmN0aW9uLiBXZSBsZWFybmVkIHRoYXQgaWYgd2UganVzdCB1c2UgYHBhcnNuaXBgIHRvIGZpdCB0aGUgbW9kZWwsIHRoZW4gd2UgbmVlZCB0byB1c2UgdGhlIHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSAob3V0cHV0IGZyb20gYGJha2UoKWApLiBXZSBsZWFybmVkIHRoYXQgd2UgY2FuIHVzZSB0aGUgcmF3IHRyYWluaW5nIGRhdGEgaWYgd2UgdXNlIHRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlIHRvIGNyZWF0ZSBhIHdvcmtmbG93IHRoYXQgcHJlLXByb2Nlc3NlcyBvdXIgZGF0YSBmb3IgdXMuICAgDQoNCldlIGxlYXJuZWQgdGhhdCBpZiB0aGUgbW9kZWwgZml0cyB3ZWxsIHRoYW4gdGhlIGVzdGltYXRlZCB2YWx1ZXMgd2lsbCBiZSB2ZXJ5IHNpbWlsYXIgdG8gdGhlIHRydWUgb3V0Y29tZSB2YXJpYWJsZSB2YWx1ZXMgaW4gb3VyIHRyYWluaW5nIGRhdGEuIFdlIGxlYXJuZWQgdGhhdCB3ZSBjYW4gYXNzZXNzIG1vZGVsIHBlcmZvcm1hbmNlIHVzaW5nIHRoZSBgeWFyZHN0aWNrYCBwYWNrYWdlIHdpdGggdGhlIGBtZXRyaWNzYCBmdW5jdGlvIG9yIHRoZSBgdHVuZWAgcGFja2FnZSBhbmQgdGhlIGBjb2xsZWN0X21ldHJpY3MoKWAgZnVuY3Rpb24gKHJlcXVpcmVkIGlmIHVzaW5nIGNyb3NzIHZhbGlkYXRpb24gb3IgdHVuaW5nKS4gV2UgYWxzbyBsZWFybmVkIHRoYXQgd2UgY2FuIHVzZSBzdWJzZXRzIG9mIG91ciB0cmFpbmluZyBkYXRhICh3aGljaCB3ZSBjcmVhdGVkIHdpdGggdGhlIGByc2FtcGxlYCBwYWNrYWdlKSB0byBwZXJmb3JtIGNyb3NzIHZhbGlkYXRpb24gdG8gZ2V0IGEgYmV0dGVyIGVzdGltYXRlIGFib3V0IHRoZSBwZXJmb3JtYW5jZSBvZiBvdXIgbW9kZWwgdXNpbmcgb3VyIHRyYWluaW5nIGRhdGEsIGFzIHdlIHdhbnQgb3VyIHJlc3VsdHMgdG8gYmUgZ2VuZXJhbGl6YWJsZSBhbmQgdG8gcGVyZm9ybSB3ZWxsIHdpdGggb3RoZXIgZGF0YSwgbm90IGp1c3Qgb3VyIHRyYWluaW5nIGRhdGEuIFdlIHVzZWQgdGhlIGBmaXRfcmVzYW1wbGVzKClgIGZ1bmN0aW9uIG9mIHRoZSB0dW5lIHBhY2thZ2UgdG8gZml0IG91ciBtb2RlbCBvbiBvdXIgZGlmZmVyZW50IHRyYWluaW5nIGRhdGEgc3Vic2V0cyBhbmQgdGhlIGBjb2xsZWN0X21ldHJpY3MoKWAgZnVuY3Rpb24gKGFsc28gb2YgdGhlIGB0dW5lYCBwYWNrYWdlKSB0byBldmFsdWF0ZSBtb2RlbCBwZXJmb3JtYW5jZSB1c2luZyB0aGVzZSBzdWJzZXRzLiAgV2UgYWxzbyBsZWFybmVkIHRoYXQgd2UgY2FuIHBvdGVudGlhbGx5IGltcHJvdmUgbW9kZWwgcGVyZm9ybWFuY2UgYnkgdHVuaW5nIGFzcGVjdHMgYWJvdXQgdGhlIG1vZGVsIGNhbGxlZCBbaHlwZXJwYXJhbWV0ZXJzXShodHRwczovL21hY2hpbmVsZWFybmluZ21hc3RlcnkuY29tL2RpZmZlcmVuY2UtYmV0d2Vlbi1hLXBhcmFtZXRlci1hbmQtYS1oeXBlcnBhcmFtZXRlci8pe3RhcmdldD0iX2JsYW5rIn0gdG8gZGV0ZXJtaW5lIHRoZSBiZXN0IG9wdGlvbiBmb3IgbW9kZWwgcGVyZm9ybWFuY2UuIFdlIGxlYXJuZWQgdGhhdCB3ZSBjYW4gZG8gdGhpcyB1c2luZyB0aGUgYHR1bmVgIGFuZCBgZGlhbHNgIHBhY2thZ2VzIGFuZCBldmFsdWF0aW5nIHRoZSBwZXJmb3JtYW5jZSBvZiBvdXIgbW9kZWwgd2l0aCB0aGUgZGlmZmVyZW50IGh5cGVycGFyYW1ldGVyIG9wdGlvbnMgYW5kIG91ciB0cmFpbmluZyBkYXRhIHN1YnNldHMgdGhhdCB3ZSB1c2VkIGZvciBjcm9zcyB2YWxpZGF0aW9uLiBBZnRlciB3ZSB0ZXN0ZWQgc2V2ZXJhbCBkaWZmZXJlbnQgbWV0aG9kcyB0byBtb2RlbCBvdXIgZGF0YSwgd2UgY29tcGFyZWQgdGhlbSB0byBjaG9vc2UgdGhlIGJlc3QgcGVyZm9ybWluZyBtb2RlbCBhcyBvdXIgZmluYWwgbW9kZWwuICANCg0KDQo1LiBPdmVyYWxsIG1vZGVsIHBlcmZvcm1hbmNlIGV2YWx1YXRpb24gIA0KDQpPbmNlIHdlIGNob3NlIG91ciBmaW5hbCBtb2RlbCwgd2UgZXZhbHVhdGVkIHRoZSBmaW5hbCBtb2RlbCBwZXJmb3JtYW5jZSB1c2luZyB0aGUgdGVzdGluZyBkYXRhIHVzaW5nIHRoZSBgbGFzdF9maXQoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlLiBUaGlzIGdpdmVzIHVzIGEgYmV0dGVyIGVzdGltYXRlIGFib3V0IGhvdyB3ZWxsIHRoZSBtb2RlbCB3aWxsIHByZWRpY3Qgb3IgY2xhc3NpZnkgdGhlIG91dGNvbWUgdmFyaWFibGUgb2YgaW50ZXJlc3Qgd2l0aCBuZXcgaW5kZXBlbmRlbnQgZGF0YS4gSWRlYWxseSBvbmUgd291bGQgYWxzbyBwZXJmb3JtIGFuIGV2YWx1YXRpb24gd2l0aCBpbmRlcGVuZGVudCBkYXRhIHRvIHByb3ZpZGUgYSBzZW5zZSBvZiBob3cgZ2VuZXJhbGl6YWJsZSB0aGUgbW9kZWwgaXMgdG8gb3RoZXIgZGF0YSBzb3VyY2VzLiANCg0KV2UgYWxzbyBzYXcgdGhhdCB3ZSBjYW4gdXNlIHRoZSBgY29sbGVjdF9wcmVkaWN0aW9ucygpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UgdG8gZ2V0IHRoZSBwcmVkaWN0aW9ucyBmb3Igb3VyIHRlc3QgZGF0YS4gV2Ugc2F3IHRoYXQgd2UgY2FuIGdldCBtb3JlIGRldGFpbGVkIHByZWRpY3Rpb24gZGF0YSB1c2luZyB0aGUgYHByZWRpY3QoKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXJzbmlwYCBwYWNrYWdlLg0KDQo8L2RldGFpbHM+DQoNCg0KDQojIyAqKlN1Z2dlc3RlZCBIb21ld29yayoqDQoqKioNCg0KU3R1ZGVudHMgY2FuIHByZWRpY3QgYWlyIHBvbGx1dGlvbiBtb25pdG9yIHZhbHVlcyB1c2luZyBhIGRpZmZlcmVudCBhbGdvcml0aG0gYW5kIHByb3ZpZGUgYW4gZXhwbGFuYXRpb24gZm9yIGhvdyB0aGF0IGFsZ29yaXRobSB3b3JrcyBhbmQgd2h5IGl0IG1heSBiZSBhIGdvb2QgY2hvaWNlIGZvciBtb2RlbGluZyB0aGlzIGRhdGEuDQoNCg0KIyAqKkFkZGl0aW9uYWwgSW5mb3JtYXRpb24qKg0KKioqDQoNCiMjICoqSGVscGZ1bCBMaW5rcyoqDQoqKioNCg0KMS4gQSByZXZpZXcgb2YgW3RpZHltb2RlbHNdKGh0dHBzOi8vcnZpZXdzLnJzdHVkaW8uY29tLzIwMTkvMDYvMTkvYS1nZW50bGUtaW50cm8tdG8tdGlkeW1vZGVscy8pe3RhcmdldD0iX2JsYW5rIn0gIA0KMi4gQSBbY291cnNlIG9uIHRpZHltb2RlbHNdKGh0dHBzOi8vanVsaWFzaWxnZS5jb20vYmxvZy90aWR5bW9kZWxzLW1sLWNvdXJzZS8pe3RhcmdldD0iX2JsYW5rIn0gYnkgSnVsaWEgU2lsZ2UgIA0KMy4gW01vcmUgZXhhbXBsZXMsIGV4cGxhbmF0aW9ucywgYW5kIGluZm8gYWJvdXQgdGlkeW1vZGVscyBkZXZlbG9wbWVudF0oaHR0cHM6Ly93d3cudGlkeW1vZGVscy5vcmcvbGVhcm4vKXt0YXJnZXQ9Il9ibGFuayJ9IGZyb20gdGhlIGRldmVsb3BlcnMgIA0KNC4gQSBndWlkZSBmb3IgW3ByZS1wcm9jZXNzaW5nIHdpdGggcmVjaXBlc10oaHR0cDovL3d3dy5yZWJlY2NhYmFydGVyLmNvbS9ibG9nLzIwMTktMDYtMDZfcHJlX3Byb2Nlc3NpbmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICANCjUuIEEgW2d1aWRlXShodHRwczovL2JyaWF0dGUuZ2l0aHViLmlvL2dnY29yci8pe3RhcmdldD0iX2JsYW5rIn0gZm9yIHVzaW5nIEdHYWxseSB0byBjcmVhdGUgY29ycmVsYXRpb24gcGxvdHMgIA0KNi4gQSBbZ3VpZGVdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvYmxvZy8yMDE4LzExL3BhcnNuaXAtMC0wLTEvKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciB1c2luZyBwYXJzbmlwIHRvIHRyeSBkaWZmZXJlbnQgYWxnb3JpdGhtcyBvciBlbmdpbmVzICANCjcuIEEgW2xpc3Qgb2YgcmVjaXBlIGZ1bmN0aW9uc10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzL3JlZmVyZW5jZS9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICANCjguIEEgZ3JlYXQgYmxvZyBwb3N0IGFib3V0IFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdHJhaW4tdGVzdC1zcGxpdC1hbmQtY3Jvc3MtdmFsaWRhdGlvbi1pbi1weXRob24tODBiNjFiZWNhNGI2KXt0YXJnZXQ9Il9ibGFuayJ9ICANCjkuIEEgZGlzY3Vzc2lvbiBhYm91dCBbZXZhbHVhdGluZyBtb2RlbCBwZXJmb3JtYW5jZV0oaHR0cHM6Ly9tZWRpdW0uY29tL0BsaW1hdmFsbGFudGluL21ldHJpY3MtdG8tbWVhc3VyZS1tYWNoaW5lLWxlYXJuaW5nLW1vZGVsLXBlcmZvcm1hbmNlLWU4Yzk2MzY2NTQ3Nil7dGFyZ2V0PSJfYmxhbmsifSBmb3IgYSBkZWVwZXIgZXhwbGFuYXRpb24gYWJvdXQgaG93IHRvIGV2YWx1YXRlIG1vZGVsIHBlcmZvcm1hbmNlICANCjEwLiBbUlN0dWRpbyBjaGVhdHNoZWV0c10oaHR0cHM6Ly9yc3R1ZGlvLmNvbS9yZXNvdXJjZXMvY2hlYXRzaGVldHMvKXt0YXJnZXQ9Il9ibGFuayJ9DQoxMS4gQW4gW2V4cGxhbmF0aW9uXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vc3VwZXJ2aXNlZC12cy11bnN1cGVydmlzZWQtbGVhcm5pbmctMTRmNjhlMzJlYThkKXt0YXJnZXQ9Il9ibGFuayJ9IG9mIHN1cGVydmlzZWQgdnMgdW5zdXBlcnZpc2VkIG1hY2hpbmUgbGVhcm5pbmcgYW5kIGJpYXMtdmFyaWFuY2UgdHJhZGUtb2ZmLg0KMTIuIEEgdGhvcm91Z2ggW2V4cGxhbmF0aW9uXShodHRwczovL3JveWFsc29jaWV0eXB1Ymxpc2hpbmcub3JnL2RvaS8xMC4xMDk4L3JzdGEuMjAxNS4wMjAyIzp+OnRleHQ9UHJpbmNpcGFsJTIwY29tcG9uZW50JTIwYW5hbHlzaXMlMjAoUENBKSUyMGlzLHZhcmlhYmxlcyUyMHRoYXQlMjBzdWNjZXNzaXZlbHklMjBtYXhpbWl6ZSUyMHZhcmlhbmNlLil7dGFyZ2V0PSJfYmxhbmsifSBvZiBwcmluY2lwYWwgY29tcG9uZW50IGFuYWx5c2lzLg0KMTMuIElmIHlvdSBoYXZlIGFjY2VzcywgdGhpcyBpcyBhIGdyZWF0IFtkaXNjdXNzaW9uXShodHRwczovL3d3dy50YW5kZm9ubGluZS5jb20vZG9pL2Ficy8xMC4xMDgwLzAwMDMxMzA1LjE5ODQuMTA0ODMxODMpe3RhcmdldD0iX2JsYW5rIn0gIGFib3V0IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gaW5kZXBlbmRlbmNlLCBvcnRob2dvbmFsaXR5LCBhbmQgbGFjayBvZiBjb3JyZWxhdGlvbi4NCjE0LiBHcmVhdCBbdmlkZW8gZXhwbGFuYXRpb25dKGh0dHBzOi8veW91dHUuYmUvX1VWSG5lQlVCVzApe3RhcmdldD0iX2JsYW5rIn0gb2YgUENBLiAgDQoNCjx1PlRlcm1zIGFuZCBjb25jZXB0cyBjb3ZlcmVkOjwvdT4gIA0KDQpbVGlkeXZlcnNlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgDQpbSW1wdXRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSW1wdXRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gIA0KW1RyYW5zZm9ybWF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EYXRhX3RyYW5zZm9ybWF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAgDQpbRGlzY3JldGl6YXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Rpc2NyZXRpemF0aW9uX29mX2NvbnRpbnVvdXNfZmVhdHVyZXMpe3RhcmdldD0iX2JsYW5rIn0gIA0KW0R1bW15IFZhcmlhYmxlc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRHVtbXlfdmFyaWFibGVfKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltPbmUtSG90IEVuY29kaW5nXShodHRwczovL21hY2hpbmVsZWFybmluZ21hc3RlcnkuY29tL3doeS1vbmUtaG90LWVuY29kZS1kYXRhLWluLW1hY2hpbmUtbGVhcm5pbmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltEYXRhIFR5cGUgQ29udmVyc2lvbnNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9oYWJsYXIvdmlnbmV0dGVzL2NvbnZlcnQuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgDQpbSW50ZXJhY3Rpb25dKGh0dHBzOi8vc3RhdGlzdGljc2J5amltLmNvbS9yZWdyZXNzaW9uL2ludGVyYWN0aW9uLWVmZmVjdHMvKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltOb3JtYWxpemF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ob3JtYWxpemF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAgDQpbRGltZW5zaW9uYWxpdHkgUmVkdWN0aW9uL1NpZ25hbCBFeHRyYWN0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaW1lbnNpb25hbGl0eV9yZWR1Y3Rpb24pe3RhcmdldD0iX2JsYW5rIn0gIA0KW1JvdyBPcGVyYXRpb25zXShodHRwczovL3RhcnRhcnVzLm9yZy9nYXJldGgvbWF0aHMvTGluZWFyX0FsZ2VicmEvcm93X29wZXJhdGlvbnMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltOZWFyIFplcm8gVmFyYWluY2VdKGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tL25lYXItemVyby12YXJpYW5jZS1wcmVkaWN0b3JzLXNob3VsZC13ZS1yZW1vdmUtdGhlbS8pe3RhcmdldD0iX2JsYW5rIn0gIA0KW1BhcmFtZXRlcnMgYW5kIEh5cGVycGFyYW1ldGVyc10oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS9kaWZmZXJlbmNlLWJldHdlZW4tYS1wYXJhbWV0ZXItYW5kLWEtaHlwZXJwYXJhbWV0ZXIvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgDQpbU3VwZXJ2aXNlZCBhbmQgVW5zcGVydmlzZWQgTGVhcm5pbmddKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS9zdXBlcnZpc2VkLXZzLXVuc3VwZXJ2aXNlZC1sZWFybmluZy0xNGY2OGUzMmVhOGQpe3RhcmdldD0iX2JsYW5rIn0gIA0KW1ByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXNdKGh0dHBzOi8vbWVkaXVtLmNvbS9Ac2F2YXN0YW1pcmtvL3BjYS1hLWxpbmVhci10cmFuc2Zvcm1hdGlvbi1mOGFhY2Q0ZWIwMDcpe3RhcmdldD0iX2JsYW5rIn0gIA0KW0xpbmVhciBDb21iaW5hdGlvbnNdKGh0dHBzOi8vd3d3Lm1hdGhib290Y2FtcHMuY29tL2xpbmVhci1jb21iaW5hdGlvbnMtdmVjdG9ycy8pe3RhcmdldD0iX2JsYW5rIn0gIA0KW0RlY2lzaW9uIFRyZWVdKGh0dHBzOi8vbWVkaXVtLmNvbS9ncmV5YXRvbS9kZWNpc2lvbi10cmVlcy1hLXNpbXBsZS13YXktdG8tdmlzdWFsaXplLWEtZGVjaXNpb24tZGM1MDZhNDAzYWViKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltSYW5kb20gRm9yZXN0XShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vZGVjaXNpb24tdHJlZS1lbnNlbWJsZXMtYmFnZ2luZy1hbmQtYm9vc3RpbmctMjY2YThiYTYwZmQ5KXt0YXJnZXQ9Il9ibGFuayJ9ICANCg0KDQogPHU+KipQYWNrYWdlcyB1c2VkIGluIHRoaXMgY2FzZSBzdHVkeToqKiA8L3U+DQoNClBhY2thZ2UgICB8IFVzZSBpbiB0aGlzIGNhc2Ugc3R1ZHkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQotLS0tLS0tLS0tIHwtLS0tLS0tLS0tLS0tDQpbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2plbm55YmMvaGVyZV9oZXJlKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgIHwgdG8gZWFzaWx5IGxvYWQgYW5kIHNhdmUgZGF0YQ0KW3JlYWRyXShodHRwczovL3JlYWRyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBpbXBvcnQgdGhlIENTViBmaWxlIGRhdGENCltkcGx5cl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gdmlldy9hcnJhbmdlL2ZpbHRlci9zZWxlY3QvY29tcGFyZSBzcGVjaWZpYyBzdWJzZXRzIG9mIHRoZSBkYXRhIA0KW3NraW1yXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGENCltzdW1tYXJ5dG9vbHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9za2ltci9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBnZXQgYW4gb3ZlcnZpZXcgb2YgZGF0YSBpbiBhIGRpZmZlcmVudCBzdHlsZQ0KW21hZ3JpdHRyXShodHRwczovL21hZ3JpdHRyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvbWFncml0dHIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gdXNlIHRoZSBgJTw+JWAgcGlwcGluZyBvcGVyYXRvciANCltjb3JycGxvdF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2NvcnJwbG90L3ZpZ25ldHRlcy9jb3JycGxvdC1pbnRyby5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gbWFrZSBsYXJnZSBjb3JyZWxhdGlvbiBwbG90cw0KW0dHYWxseV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL0dHYWxseS9HR2FsbHkucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gbWFrZSBzbWFsbGVyIGNvcnJlbGF0aW9uIHBsb3RzICANCltyc2FtcGxlXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JzYW1wbGUvYXJ0aWNsZXMvQmFzaWNzLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHNwbGl0IHRoZSBkYXRhIGludG8gdGVzdGluZyBhbmQgdHJhaW5pbmcgc2V0cyBhbmQgdG8gc3BsaXQgdGhlIHRyYWluaW5nIHNldCBmb3IgY3Jvc3MtdmFsaWRhdGlvbiAgDQpbcmVjaXBlc10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gcHJlLXByb2Nlc3MgZGF0YSBmb3IgbW9kZWxpbmcgaW4gYSB0aWR5IGFuZCByZXByb2R1Y2libGUgd2F5IGFuZCB0byBleHRyYWN0IHByZS1wcm9jZXNzZWQgZGF0YSAobWFqb3IgZnVuY3Rpb25zIGFyZSBgcmVjaXBlKClgICwgYHByZXAoKWAgYW5kIHZhcmlvdXMgdHJhbnNmb3JtYXRpb24gYHN0ZXBfKigpYCBmdW5jdGlvbnMsIGFzIHdlbGwgYXMgYGJha2VgIHdoaWNoIGV4dHJhY3RzIHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSAodXNlZCB0byByZXF1aXJlIGBqdWljZSgpYCkgYW5kIGFwcGxpZXMgcmVjaXBlIHByZXByb2Nlc3Npbmcgc3RlcHMgdG8gdGVzdGluZyBkYXRhKS4gU2VlIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmVjaXBlcy9yZWNpcGVzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgZm9yIG1vcmUgaW5mby4NCltwYXJzbmlwXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3BhcnNuaXAvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCBhbiBpbnRlcmZhY2UgdG8gY3JlYXRlIG1vZGVscyAobWFqb3IgZnVuY3Rpb25zIGFyZSAgYGZpdCgpYCwgYHNldF9lbmdpbmUoKWApDQpbeWFyZHN0aWNrXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3lhcmRzdGljay8pe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIGV2YWx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiBtb2RlbHMNClticm9vbV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy9ibG9nLzIwMTgvMDcvYnJvb20tMC01LTAvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IHRpZHkgb3V0cHV0IGZvciBvdXIgbW9kZWwgZml0IGFuZCBwZXJmb3JtYW5jZQ0KW2dncGxvdDJdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1ha2UgdmlzdWFsaXphdGlvbnMgd2l0aCBtdWx0aXBsZSBsYXllcnMNCltkaWFsc10oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy9ibG9nLzIwMTkvMTAvZGlhbHMtMC0wLTMvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gc3BlY2lmeSBoeXBlci1wYXJhbWV0ZXIgdHVuaW5nDQpbdHVuZV0oaHR0cHM6Ly90dW5lLnRpZHltb2RlbHMub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHBlcmZvcm0gY3Jvc3MgdmFsaWRhdGlvbiwgdHVuZSBoeXBlci1wYXJhbWV0ZXJzLCBhbmQgZ2V0IHBlcmZvcm1hbmNlIG1ldHJpY3MNClt3b3JrZmxvd3NdKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy93b3JrZmxvd3MvdmVyc2lvbnMvMC4xLjEpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBjcmVhdGUgbW9kZWxpbmcgd29ya2Zsb3cgdG8gc3RyZWFtbGluZSB0aGUgbW9kZWxpbmcgcHJvY2Vzcw0KW3ZpcF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3ZpcC92aXAucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gY3JlYXRlIHZhcmlhYmxlIGltcG9ydGFuY2UgcGxvdHMNCltyYW5kb21Gb3Jlc3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yYW5kb21Gb3Jlc3QvcmFuZG9tRm9yZXN0LnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHBlcmZvcm0gdGhlIHJhbmRvbSBmb3Jlc3QgYW5hbHlzaXMNCltkb1BhcmFsbGVsXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZG9QYXJhbGxlbC9kb1BhcmFsbGVsLnBkZikgfCB0byBmaXQgY3Jvc3MgdmFsaWRhdGlvbiBzYW1wbGVzIGluIHBhcmFsbGVsIA0KW3N0cmluZ3JdKGh0dHBzOi8vc3RyaW5nci50aWR5dmVyc2Uub3JnL2FydGljbGVzL3N0cmluZ3IuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1hbmlwdWxhdGUgdGhlIHRleHQgdGhlIG1hcCBkYXRhDQpbdGlkeXJdKGh0dHBzOi8vdGlkeXIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHNlcGFyYXRlIGRhdGEgd2l0aGluIGEgY29sdW1uIGludG8gbXVsdGlwbGUgY29sdW1ucw0KW3JuYXR1cmFsZWFydGhdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ybmF0dXJhbGVhcnRoL1JFQURNRS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IHRoZSBnZW9tZXRyeSBkYXRhIGZvciB0aGUgZWFydGggdG8gcGxvdCB0aGUgVVMNClttYXBzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbWFwcy9tYXBzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGdldCBtYXAgZGF0YWJhc2UgZGF0YSBhYm91dCBjb3VudGllcyB0byBkcmF3IHRoZW0gb24gb3VyIFVTIG1hcA0KW3NmXShodHRwczovL3Itc3BhdGlhbC5naXRodWIuaW8vc2YvKXt0YXJnZXQ9Il9ibGFuayJ9ICB8IHRvIGNvbnZlcnQgdGhlIG1hcCBkYXRhIGludG8gYSBkYXRhIGZyYW1lDQpbbHdnZW9tXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbHdnZW9tL2x3Z2VvbS5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byB1c2UgdGhlIGBzZmAgZnVuY3Rpb24gdG8gY29udmVydCB0aGUgbWFwIGdlb2dyYXBoaWNhbCBkYXRhDQpbcmdlb3NdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZ2Vvcy9yZ2Vvcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byB1c2UgZ2VvbWV0cnkgZGF0YQ0KW3BhdGNod29ya10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3BhdGNod29yay9wYXRjaHdvcmsucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gYWxsb3cgcGxvdHMgdG8gYmUgY29tYmluZWQNCg0KDQojIyAqKlNlc3Npb24gaW5mbyoqDQoqKioNCg0KDQpgYGB7cn0NCnNlc3Npb25JbmZvKCkNCmBgYA0KDQoNCiMjICoqQWNrbm93bGVkZ21lbnRzKioNCioqKg0KDQoNCldlIHdvdWxkIGxpa2UgdG8gYWNrbm93bGVkZ2UgW1JvZ2VyIFBlbmddKGh0dHA6Ly93d3cuYmlvc3RhdC5qaHNwaC5lZHUvfnJwZW5nLyksIFtNZWdhbiBMYXRzaGF3XShodHRwczovL3d3dy5qaHNwaC5lZHUvZmFjdWx0eS9kaXJlY3RvcnkvcHJvZmlsZS8xNzA4L21lZ2FuLXdlaWwtbGF0c2hhdyksIGFuZCBbS2lyc3RlbiBLb2VobGVyXShodHRwczovL3d3dy5qaHNwaC5lZHUvZmFjdWx0eS9kaXJlY3RvcnkvcHJvZmlsZS8yOTI4L2tpcnN0ZW4ta29laGxlcikgZm9yIGFzc2lzdGluZyBpbiBmcmFtaW5nIHRoZSBtYWpvciBkaXJlY3Rpb24gb2YgdGhlIGNhc2Ugc3R1ZHkuDQoNCldlIHdvdWxkIGFsc28gbGlrZSB0byBhY2tub3dsZWRnZSB0aGUgW0Jsb29tYmVyZyBBbWVyaWNhbiBIZWFsdGggSW5pdGlhdGl2ZV0oaHR0cHM6Ly9hbWVyaWNhbmhlYWx0aC5qaHUuZWR1LykgZm9yIGZ1bmRpbmcgdGhpcyB3b3JrLiANCg0KPHNjcmlwdD4NCiAgaUZyYW1lUmVzaXplKHt9LCAiLmludGVyYWN0aXZlIik7DQo8L3NjcmlwdD4=